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