Subversion Repositories XServices

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
175 brianR 1
/*
2
 *   Copyright 2014 Brian Rosenberger (Brutex Network)
3
 *
4
 *   Licensed under the Apache License, Version 2.0 (the "License");
5
 *   you may not use this file except in compliance with the License.
6
 *   You may obtain a copy of the License at
7
 *
8
 *       http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *   Unless required by applicable law or agreed to in writing, software
11
 *   distributed under the License is distributed on an "AS IS" BASIS,
12
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *   See the License for the specific language governing permissions and
14
 *   limitations under the License.
15
 */
16
 
17
package net.brutex.xservices.ws.rs;
18
 
19
 
20
 
21
import java.io.File;
22
import java.io.IOException;
23
import java.net.MalformedURLException;
24
import java.net.URI;
25
import java.net.URL;
26
import java.nio.file.FileVisitOption;
27
import java.nio.file.Files;
28
import java.nio.file.Path;
29
import java.util.ArrayList;
30
import java.util.EnumSet;
31
import java.util.List;
32
import javax.ws.rs.core.HttpHeaders;
33
import javax.ws.rs.core.Response;
34
import javax.ws.rs.core.UriInfo;
35
 
36
import net.brutex.xservices.cmtypes.ItemType;
37
import net.brutex.xservices.cmtypes.ItemTypeList;
38
import net.brutex.xservices.types.FileInfoType;
39
import net.brutex.xservices.util.FileWalker;
40
 
41
import org.apache.commons.configuration.ConfigurationException;
42
import org.apache.commons.configuration.PropertiesConfiguration;
43
import org.apache.jcs.JCS;
44
import org.apache.jcs.access.exception.CacheException;
45
import org.apache.log4j.Logger;
46
 
47
 
48
/*
49
 * The Serena Dimensions CM Java API is required for these imports.
50
 * The API is not included in this package due to copyright reasons,
51
 * please get Dimensions CM from Serena Software Inc., Evaluation versions
52
 * are available from http://www.serena.com
53
 *
54
 * required Jars:
55
 * serena.darius-14.1.jar
56
 * serena.dmclient-14.1.jar
57
 * serena.dmfile-14.1.jar
58
 * serena.dmnet-14.1.jar
59
 * serena.dmtpi-14.1.jar
60
 *
61
 */
62
 
63
import com.serena.dmclient.api.BulkOperator;
64
import com.serena.dmclient.api.DimensionsConnection;
65
import com.serena.dmclient.api.DimensionsConnectionDetails;
66
import com.serena.dmclient.api.DimensionsConnectionManager;
67
import com.serena.dmclient.api.ItemRevision;
68
import com.serena.dmclient.api.Project;
69
import com.serena.dmclient.api.RepositoryFolder;
70
import com.serena.dmclient.api.SystemAttributes;
71
 
72
/**
73
 * The Class FileInfoImpl.
74
 *
75
 * @author Brian Rosenberger, bru(at)brutex.de
76
 */
77
public class DIMCMInfoImpl implements DIMCMInfo {
78
 
79
	Logger logger = Logger.getLogger(DIMCMInfoImpl.class);
80
 
81
	/*
82
	 * (non-Javadoc)
83
	 *
84
	 * @see
85
	 * net.brutex.xservices.ws.rs.FileInfo#getFiles(javax.ws.rs.core.HttpHeaders
86
	 * , java.lang.String, boolean, boolean, int, java.lang.String, int, int)
87
	 */
88
	public Response getFiles(HttpHeaders h, UriInfo uriInfo, String projSpec,
89
			String directory, boolean recursive, boolean withFiles, int level,
90
			String search, int count, int page, boolean useCache) throws CacheException {
91
 
92
 
93
		/*
94
		 * try to hit cache first
95
		 */
96
		JCS cache = JCS.getInstance("DIMCM");
97
		String cachekey = projSpec + directory + String.valueOf(recursive);
98
		if(useCache) {
99
				ItemTypeList cacheresult = (ItemTypeList) cache.get(cachekey);
100
				if(cacheresult != null) return Response.ok(cacheresult).build();
101
		}
102
 
103
		//Reject when project has not the form "PRODUCT:PROJECT"
104
		if(! projSpec.contains(":")) return Response.noContent().build();
105
 
106
		Project project = getDIMCMConnection().getObjectFactory().getProject(projSpec);
107
		RepositoryFolder folder = null;
108
 
109
		if (directory == null) {
110
			folder = project.getRootFolder();
111
		} else {
112
			while(directory.startsWith("/") || directory.startsWith("\\")) {
113
				directory = directory.substring(1);
114
			}
115
			if(directory.equals("")) {
116
				folder = project.getRootFolder();
117
			} else {
118
				folder = project.findRepositoryFolderByPath(directory);
119
			}
120
		}
121
 
122
 
123
		ItemTypeList resultlist = new ItemTypeList();
124
		resultlist.list = getItems(folder, recursive);
125
		if(cache!=null) cache.put(cachekey, resultlist);
126
 
127
		//does this help?
128
		DimensionsConnectionManager.unregisterThreadConnection();
129
 
130
		return Response.ok(resultlist).build();
131
 
132
	}
133
 
134
 
135
 
136
 
137
	List<ItemType> getItems(RepositoryFolder f, boolean recursive) {
138
		DimensionsConnection conn = getDIMCMConnection();
139
		List<ItemType> result = new ArrayList<>();
140
 
141
		/* get Items from current folder */
142
		/* latest revision only */
143
		List<ItemRevision> revisions = f.getLatestItemRevisions();
144
 
145
		int[] attr = { SystemAttributes.FULL_PATH_NAME,
146
				SystemAttributes.ITEMFILE_DIR,
147
				SystemAttributes.ITEMFILE_FILENAME,
148
				SystemAttributes.ITEMFILE_DIR, SystemAttributes.OBJECT_SPEC,
149
				SystemAttributes.OBJECT_ID, SystemAttributes.OBJECT_SPEC_UID,
150
				SystemAttributes.OBJECT_UID, SystemAttributes.CREATION_DATE,
151
				SystemAttributes.CREATION_USER, SystemAttributes.ITEM_FORMAT,
152
				SystemAttributes.LAST_UPDATED_DATE,
153
				SystemAttributes.LAST_UPDATED_USER };
154
		BulkOperator bulk = conn.getObjectFactory().getBulkOperator(revisions);
155
		bulk.queryAttribute(attr);
156
 
157
		// Copy into JAXB object
158
		for (ItemRevision r : revisions) {
159
			ItemType item = new ItemType();
160
			item.setLongFilename((String) r
161
					.getAttribute(SystemAttributes.FULL_PATH_NAME));
162
			item.setDirName((String) r
163
					.getAttribute(SystemAttributes.ITEMFILE_DIR));
164
			item.setShortFilename((String) r
165
					.getAttribute(SystemAttributes.ITEMFILE_FILENAME));
166
			item.setObject_id((String) r
167
					.getAttribute(SystemAttributes.OBJECT_ID));
168
			item.setObject_uid((String.valueOf(r
169
					.getAttribute(SystemAttributes.OBJECT_UID))));
170
			item.setObject_spec((String) r
171
					.getAttribute(SystemAttributes.OBJECT_SPEC));
172
			item.setObject_spec_uid(String.valueOf(r
173
					.getAttribute(SystemAttributes.OBJECT_SPEC_UID)));
174
			item.setObject_spec_uid(String.valueOf(r
175
					.getAttribute(SystemAttributes.OBJECT_SPEC_UID)));
176
			item.setCreatedDate(String.valueOf(r
177
					.getAttribute(SystemAttributes.CREATION_DATE)));
178
			item.setCreatedUser(String.valueOf(r
179
					.getAttribute(SystemAttributes.CREATION_USER)));
180
			item.setItemFormat(String.valueOf(r
181
					.getAttribute(SystemAttributes.ITEM_FORMAT)));
182
			item.setUpdatedDate(String.valueOf(r
183
					.getAttribute(SystemAttributes.LAST_UPDATED_DATE)));
184
			item.setUpdatedUser(String.valueOf(r
185
					.getAttribute(SystemAttributes.LAST_UPDATED_USER)));
186
 
187
			try {
188
				item.setUrl(new URL(getBaseURL()
189
						+ "?jsp=api&command=openi&object_id="
190
						+ item.getObject_spec() + "&DB_CONN="
191
						+ conn.getConnectionDetails().getDbConn() + "&DB_NAME="
192
						+ conn.getConnectionDetails().getDbName()));
193
			} catch (MalformedURLException e) {
194
				// TODO Auto-generated catch block
195
				e.printStackTrace();
196
			}
197
			result.add(item);
198
		}
199
 
200
		/*
201
		 * for recursive add other folders
202
		 */
203
		if(recursive) {
204
			List<RepositoryFolder> folders = f.getAllChildFolders();
205
			for(RepositoryFolder ff : folders) {
206
				result.addAll(getItems(ff, false));
207
			}
208
		}
209
 
210
		return result;
211
	}
212
 
213
	/**
214
	 * Sets the directory.
215
	 *
216
	 * @param list
217
	 *            the list
218
	 * @param dir
219
	 *            the dir
220
	 * @param withDirectories
221
	 *            the with directories
222
	 * @param withFiles
223
	 *            the with files
224
	 * @param depth
225
	 *            the depth
226
	 * @param search
227
	 *            the search
228
	 */
229
	private void setDirectory(final URI baseuri, final List<FileInfoType> list,
230
			File dir, boolean withDirectories, boolean withFiles,
231
			final int depth, String search) {
232
		if (depth <= 0)
233
			return;
234
 
235
		if (search == null || search.equals("")) {
236
			search = "*";
237
			logger.info("No search pattern supplied, using default '*'.");
238
		}
239
 
240
		FileWalker finder = new FileWalker(search);
241
		try {
242
			Files.walkFileTree(dir.toPath(),
243
					EnumSet.of(FileVisitOption.FOLLOW_LINKS), depth, finder);
244
			logger.info("FileWalker returned '" + finder.getCount()
245
					+ "' hits. '" + finder.getTotal()
246
					+ "' files have been scanned.");
247
			List<Path> result = finder.getResult();
248
			for (Path f : result) {
249
				if (!withDirectories) {
250
					if (f.toFile().isDirectory())
251
						continue;
252
				}
253
				if (!withFiles) {
254
					if (f.toFile().isFile())
255
						continue;
256
				}
257
				list.add(new FileInfoType(f, baseuri));
258
			}
259
		} catch (IOException e2) {
260
			logger.error(e2.getMessage(), e2);
261
			;
262
		}
263
	}
264
 
265
	/**
266
	 * Sets the directory.
267
	 *
268
	 * @param dir
269
	 *            the dir
270
	 * @param withDirectories
271
	 *            the with directories
272
	 * @param withFiles
273
	 *            the with files
274
	 * @param depth
275
	 *            the depth
276
	 * @param search
277
	 *            the search
278
	 * @return the list
279
	 */
280
	private List<FileInfoType> setDirectory(URI baseuri, String dir,
281
			boolean withDirectories, boolean withFiles, int depth, String search) {
282
		List<FileInfoType> list = new ArrayList<FileInfoType>();
283
		setDirectory(baseuri, list, new File(dir), withDirectories, withFiles,
284
				depth, search);
285
		return list;
286
	}
287
 
288
	private boolean isPermitted(String dir) {
289
		/*
290
		 *
291
		 * logger.warn(String.format(
292
		 * "User '%s' does not have permission to access '%s'."
293
		 * ,SecurityUtils.getSubject().getPrincipal(), dir )); throw new
294
		 * NotAuthorizedException(new
295
		 * UnauthorizedException("User does not have permission to access "+
296
		 * dir)); }
297
		 */
298
		return true;
299
	}
300
 
301
	// http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
302
	private static String humanReadableByteCount(long bytes, boolean si) {
303
		int unit = si ? 1000 : 1024;
304
		if (bytes < unit)
305
			return bytes + " B";
306
		int exp = (int) (Math.log(bytes) / Math.log(unit));
307
		String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1)
308
				+ (si ? "" : "i");
309
		return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
310
	}
311
 
312
	private DimensionsConnection getDIMCMConnection() {
313
		/*
314
		 * Do we have a registered connection already?
315
		 */
316
		DimensionsConnection conn = null;
317
 
318
		try {
319
			conn = DimensionsConnectionManager.getThreadConnection();
320
			if (conn != null)
321
				return conn;
322
		} catch (Exception e) {
323
			logger.error(e.getMessage());
324
		}
325
 
326
		/*
327
		 * Create a new connection from property file
328
		 */
329
		PropertiesConfiguration props;
330
		try {
331
			props = new PropertiesConfiguration(this.getClass()
332
					.getClassLoader().getResource("/../dimcm.properties"));
333
		} catch (ConfigurationException e) {
334
			e.printStackTrace();
335
			return null;
336
		}
337
 
338
		DimensionsConnectionDetails details = new DimensionsConnectionDetails();
339
		details.setUsername(props.getString("user"));
340
		details.setPassword(props.getString("password"));
341
		details.setDbName(props.getString("dbname"));
342
		details.setDbConn(props.getString("dbconn"));
343
		details.setServer(props.getString("server"));
344
		conn = DimensionsConnectionManager.getConnection(details);
345
		DimensionsConnectionManager.registerThreadConnection(conn);
346
		return conn;
347
	}
348
 
349
	private String getBaseURL() {
350
		final String CACHE_BASEURL = "DIMCM.conf.baseurl";
351
	try {
352
		JCS cache = JCS.getInstance("DIMCM");
353
		String baseurl = (String) cache.get(CACHE_BASEURL);
354
		if(baseurl != null) return baseurl;
355
 
356
		PropertiesConfiguration	props = new PropertiesConfiguration(this.getClass().getClassLoader().getResource("/../dimcm.properties"));
357
		baseurl = props.getString("baseurl");
358
		cache.put(CACHE_BASEURL, baseurl);
359
		return baseurl;
360
 
361
	} catch (CacheException e1) {
362
		// TODO Auto-generated catch block
363
		e1.printStackTrace();
364
		return null;
365
	} catch (ConfigurationException e) {
366
		e.printStackTrace();
367
		return null;
368
 
369
	}
370
}
371
}