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    }