001 package opendreams.proxy;
002
003 import java.util.ArrayList;
004 import java.util.Calendar;
005 import java.util.HashSet;
006 import java.util.List;
007 import java.util.Set;
008
009 import tecgraf.ftc.common.logic.RemoteFileChannel;
010 import tecgraf.ftc.common.logic.RemoteFileChannelImpl;
011 import tecgraf.ftc.utils.Utils;
012 import tecgraf.openbus.data_service.DataDescription;
013 import tecgraf.openbus.data_service.DataKey;
014 import tecgraf.openbus.data_service.IHierarchicalDataService;
015 import tecgraf.openbus.data_service.Metadata;
016 import tecgraf.openbus.data_service.UnstructuredData;
017 import tecgraf.openbus.data_service.UnstructuredDataHelper;
018 import tecgraf.openbus.project.ProjectItemDescription;
019 import tecgraf.openbus.project.ProjectItemDescriptionHelper;
020 import tecgraf.openbus.data_service.project.ProjectItemDescriptionImpl;
021
022 /**
023 * Um projeto usado para escrever e ler arquivos usados na submissão de comandos
024 * pelo OpenDreams.
025 *
026 * @author Tecgraf PUC-Rio
027 */
028 public class Project {
029 private IHierarchicalDataService dataService;
030 private DataDescription projectDesc;
031 private String owner;
032 private byte[] currentDir;
033
034 /**
035 * Constrói uma representação do projeto.
036 *
037 * @param projectDesc descritor do projeto
038 * @param owner nome do usuário
039 * @param dataService serviço de projeto
040 */
041 Project(DataDescription projectDesc, String owner,
042 IHierarchicalDataService dataService) {
043 this.projectDesc = projectDesc;
044 this.dataService = dataService;
045 this.owner = owner;
046 this.currentDir = projectDesc.fKey;
047 }
048
049 /**
050 * Altera o diretório corrente.
051 *
052 * @param dirName nome do diretório
053 * @return verdadeiro, se já existe um diretório com o nome fornecido ou
054 * falso, caso contrário.
055 * @throws OpenDreamsException
056 */
057 public boolean changeDirectory(String dirName) throws OpenDreamsException {
058 return changeDirectory(dirName, false);
059 }
060
061 /**
062 * Altera o diretório para um outro que seja filho do diretório corrente.
063 *
064 * @param dirName nome do diretório filho
065 * @param create se verdadeiro, cria o diretório se não existir
066 * @return verdadeiro, se o diretório corrente foi alterado ou falso, caso
067 * contrário.
068 * @throws OpenDreamsException
069 */
070 public boolean changeDirectory(String dirName, boolean create)
071 throws OpenDreamsException {
072 byte[] fkey = this.find(dirName);
073 if (fkey != null) {
074 this.currentDir = fkey;
075 return true;
076 }
077 if (create) {
078 return createDirectory(dirName, true);
079 }
080 return false;
081 }
082
083 /**
084 * Cria um diretório filho do diretório corrente.
085 *
086 * @param dirName nome do diretório
087 * @param change se verdadeiro, faz com o que o novo diretório seja o corrente
088 * @return verdadeiro, se o diretório foi criado e falso, caso contrário.
089 * @throws OpenDreamsException
090 */
091 public boolean createDirectory(String dirName, boolean change)
092 throws OpenDreamsException {
093 Set<String> views = new HashSet<String>();
094 views.add(ProjectItemDescriptionHelper.id());
095 long currentDate = Calendar.getInstance().getTimeInMillis();
096 ProjectItemDescription prototype =
097 new ProjectItemDescriptionImpl(dirName, views, new ArrayList<Metadata>(),
098 owner, null, null, null, 0, true, true, true, currentDate, currentDate);
099 try {
100 byte[] key = dataService.createData(currentDir, prototype);
101 if (change) {
102 this.currentDir = key;
103 }
104 return true;
105 }
106 catch (Exception e) {
107 throw new OpenDreamsException("Erro na criação do diretório " + dirName
108 + " no projeto " + projectDesc.fName, e);
109 }
110 }
111
112 /**
113 * Cria um diretório filho do diretório corrente.
114 *
115 * @param dirName nome do diretório
116 * @return verdadeiro, se o diretório foi criado e falso, caso contrário.
117 * @throws OpenDreamsException
118 */
119 public boolean createDirectory(String dirName) throws OpenDreamsException {
120 return createDirectory(dirName, false);
121 }
122
123 /**
124 * Obtém os dados de um arquivo que está no diretório corrente da área do
125 * projeto.
126 *
127 * @param fileName nome do arquivo
128 * @return o array com os bytes lidos
129 * @throws OpenDreamsException
130 */
131 public byte[] getDataFrom(String fileName) throws OpenDreamsException {
132 byte[] fileKey = this.find(fileName);
133 if (fileKey == null) {
134 throw new OpenDreamsException("Arquivo " + fileName + " não encontrado");
135 }
136 try {
137 UnstructuredData view =
138 (UnstructuredData) dataService.getDataView(fileKey,
139 UnstructuredDataHelper.id());
140 DataKey dataKey = new DataKey(view.fKey);
141 RemoteFileChannel rfc =
142 new RemoteFileChannelImpl(dataKey.getDataId().getBytes(
143 Utils.CHARSET_ENCODING), view.fWritable, view.fHost, view.fPort,
144 view.fAccessKey);
145 System.out.println("Host: " + view.fHost);
146 System.out.println("Port: " + view.fPort);
147 rfc.open(true);
148 int fileSize = (int) rfc.getSize();
149 byte[] buffer = new byte[fileSize];
150 rfc.read(buffer);
151 rfc.close();
152 return buffer;
153 }
154 catch (Exception e) {
155 throw new OpenDreamsException("Erro na leitura de um dado no projeto", e);
156 }
157 }
158
159 /**
160 * Grava os dados em um arquivo que está no diretório corrente da área do
161 * projeto.
162 *
163 * @param fileName nome do arquivo
164 * @param data o array com os bytes a serem escritos no arquivo
165 * @throws OpenDreamsException
166 */
167 public void createFile (String fileName, byte[] data) throws OpenDreamsException {
168 byte[] fileKey = this.find(fileName);
169 if (fileKey != null) {
170 throw new OpenDreamsException("Arquivo " + fileName + " já existe");
171 }
172 try {
173 Set<String> views = new HashSet<String>();
174 views.add(ProjectItemDescriptionHelper.id());
175 long currentDate = Calendar.getInstance().getTimeInMillis();
176 ProjectItemDescription prototype =
177 new ProjectItemDescriptionImpl(fileName, views,
178 new ArrayList<Metadata>(), owner, null, null, null, 0, false, true,
179 true, currentDate, currentDate);
180 fileKey = dataService.createData(currentDir, prototype);
181 UnstructuredData view =
182 (UnstructuredData) dataService.getDataView(fileKey,
183 UnstructuredDataHelper.id());
184 DataKey dataKey = new DataKey(view.fKey);
185 RemoteFileChannel rfc =
186 new RemoteFileChannelImpl(dataKey.getDataId().getBytes(
187 Utils.CHARSET_ENCODING), view.fWritable, view.fHost, view.fPort,
188 view.fAccessKey);
189 rfc.open(false);
190 rfc.write(data);
191 rfc.close();
192 }
193 catch (Exception e) {
194 throw new OpenDreamsException("Erro na criação de um arquivo no projeto", e);
195 }
196 }
197
198 /**
199 * Remove um arquivo do projeto. O arquivo precisa existir.
200 *
201 * @param fileName nome do arquivo
202 * @throws OpenDreamsException
203 */
204 public void removeFile(String fileName) throws OpenDreamsException {
205 byte[] fileKey = this.find(fileName);
206 if (fileKey == null) {
207 throw new OpenDreamsException("Arquivo " + fileName + " não existe");
208 }
209 try {
210 dataService.deleteData(fileKey);
211 }
212 catch (Exception e) {
213 throw new OpenDreamsException("Erro na remoção do arquivo " + fileName, e);
214 }
215 }
216
217 /**
218 * Verifica se um arquivo ou diretório existe no projeto.
219 *
220 * @param fileName nome do arquivo ou diretório
221 * @return verdadeiro, se existe e falso, caso contrário
222 * @throws OpenDreamsException
223 */
224 public boolean hasFile (String fileName) throws OpenDreamsException {
225 try {
226 return this.find(fileName) != null;
227 }
228 catch (Exception e) {
229 throw new OpenDreamsException("Erro na consulta se o arquivo " + fileName + " existe", e);
230 }
231 }
232
233 /**
234 * Nome do projeto.
235 *
236 * @return o nome do projeto
237 */
238 public String getName() {
239 return projectDesc.fName;
240 }
241
242 /**
243 * Retorna a chave para um arquivo ou um diretório filho do diretório
244 * corrente.
245 *
246 * @param name nome do arquivo ou diretório procurado
247 * @return a chave do arquivo procurado ou null caso ele não exista
248 * @throws OpenDreamsException
249 */
250 private byte[] find(String name) throws OpenDreamsException {
251 byte[] fileKey = null;
252 DataDescription[] descriptions;
253 try {
254 descriptions = dataService.getChildren(currentDir);
255 for (DataDescription descr : descriptions) {
256 if (descr.fName.equals(name)) {
257 fileKey = descr.fKey;
258 break;
259 }
260 }
261 }
262 catch (Exception e) {
263 throw new OpenDreamsException(
264 "Erro na procura pelo arquivo ou diretório " + name, e);
265 }
266 return fileKey;
267 }
268
269 /**
270 * Retorna lista de nomes de arquivos e diretórios do diretório corrente.
271 *
272 * @return lista com OpenDreamsException de arquivos e diretórios do diretório corrente.
273 * @throws OpenDreamsException
274 */
275 public List<String> list() throws OpenDreamsException {
276 ArrayList<String> fileNames = new ArrayList<String>();
277 DataDescription[] descriptions;
278 try {
279 descriptions = dataService.getChildren(currentDir);
280 for (DataDescription descr : descriptions) {
281 fileNames.add(descr.fName);
282 }
283 }
284 catch (Exception e) {
285 throw new OpenDreamsException("Erro na listagem do diretório: "
286 + currentDir, e);
287 }
288 return fileNames;
289 }
290
291 /**
292 * Verifica se uma data entrada é um diretório ou não.
293 *
294 * @param entryName
295 * @return true se é diretório, false se for arquivo
296 * @throws OpenDreamsException
297 */
298 public boolean isDirectory(String entryName) throws OpenDreamsException {
299 try {
300 ProjectItemDescription descr =
301 (ProjectItemDescription) dataService.getDataDescription(this
302 .find(entryName));
303 return descr.fIsContainer;
304 }
305 catch (Exception e) {
306 throw new OpenDreamsException("Erro ao checar se " + entryName
307 + " é diretório.", e);
308 }
309 }
310 }