1. Create a Maven project with Eclipse (and arrange the pom.xml file)
File-New-Maven project
Press Next
The Artifact ID is the name of the project
Now modify the pom.xml file and add the yellow lines to match this file (One dependency for opencmis and another to manage files, both from Apache):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.ximodante</groupId> <artifactId>OpenCMIS01</artifactId> <version>0.0.1-SNAPSHOT</version> <name>OpenCMIS01</name> <description>OpenCMIS01 first project</description> <dependencies> <!-- https://mvnrepository.com/artifact/org.apache.chemistry.opencmis/chemistry-opencmis-client-impl --> <dependency> <groupId>org.apache.chemistry.opencmis</groupId> <artifactId>chemistry-opencmis-client-impl</artifactId> <version>1.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> </dependencies> </project> |
2. Authentication (in an existing installation), accessing the Alfresco URL, and get repositories
These are the main steps:
- Create a HashMap
- Feed the map with: user, password, binding protocol and Alfresco server URL. Note the special URL to access the server.
- Get a SessionFactory
- Use the SessionFactory to select a repository (usually the first one)
- Create a Session and do some stuff with this repository
In addition, a utility method for printing nested objects is supplied
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | package tests; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.chemistry.opencmis.client.api.CmisObject; import org.apache.chemistry.opencmis.client.api.Folder; import org.apache.chemistry.opencmis.client.api.ItemIterable; import org.apache.chemistry.opencmis.client.api.QueryResult; import org.apache.chemistry.opencmis.client.api.Repository; import org.apache.chemistry.opencmis.client.api.Session; import org.apache.chemistry.opencmis.client.api.SessionFactory; import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; import org.apache.chemistry.opencmis.commons.SessionParameter; import org.apache.chemistry.opencmis.commons.data.PropertyData; import org.apache.chemistry.opencmis.commons.enums.BindingType; public class Test02 { /** * Utility method to print INFO from a CMIS object * @param obj * @param level * @param maxLevel */ private static void printCmisObject(CmisObject obj, int level, int maxLevel) { if (level<=maxLevel) { String spaces=""; for (int i=0; i<level; i++) spaces=spaces+" "; System.out.println(spaces + obj.getId()+ "-"+ obj.getName()+ "-" + obj.getType()); if (obj instanceof Folder) { for (CmisObject child: ((Folder) obj).getChildren()) { printCmisObject(child,level+1, maxLevel); } } } } public static void main(String[] args) { //1. creaqte a map Map<String, String> parameters = new HashMap<String, String>(); // 2. user credentials parameters.put(SessionParameter.USER, "myuser"); parameters.put(SessionParameter.PASSWORD, "mypassword"); // 3. connection settings parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); // Since Alfresco Version 4.xx on @ see https://stackoverflow.com/a/41601409/7704658 parameters.put(SessionParameter.ATOMPUB_URL,"http://127.0.0.1:8080/alfresco/cmisatom"); // 4. Create a session factory SessionFactory factory = SessionFactoryImpl.newInstance(); //5. Get repositories !! List<Repository> repositories = factory.getRepositories(parameters); for (Repository rep : repositories) { System.out.println(rep.getId()+ " " + rep.getDescription()); } //5. Create a session on the first repository Session session = repositories.get(0).createSession(); //6.1 Get the root folder and print children Folder rootFolder = session.getRootFolder(); //List all children printCmisObject(rootFolder,0,3); //6.2. Queries name and id by document name. Note that the query gets only up to 100 records ItemIterable<QueryResult> results = session.query( " SELECT cmis:name , cmis:objectId " + " FROM cmis:document " + " WHERE cmis:name like '%1553072%'" ,false); int i=0; for(QueryResult hit: results) { i++; for(PropertyData<?> property: hit.getProperties()) { String queryName = property.getQueryName(); Object value = property.getFirstValue(); System.out.println(i+" "+queryName + ": " + value + " "); } } } } |
Let's explain the code:
- Lines 26-37: Utility for printing objects' info and showing nested objects.
- Line 41: Creation of a HashMap that stores the properties
- Lines44-45: Introduction of credentials
- Line 48: Set binding type to AtomPub. Other bindings are available as SOAP, CMIS 1.1
- Line 50: Alfresco server URL. Note the structure: IP+":" + Port+/"alfresco/cmisatom"
- Line 53: Create a SessionFactory object
- Line 56: Get all repositories from the SessionFactory object.
- Line 61: Creates a Session to manage all elements from the repository
- Lines 62-66: Shows all the objects from the root folder
- Lines 69-80: Executes a query to extract some info from a document, searching by part of its name and it does not matter in which node in the tree structure it is.
Reference: Apache Chemestry
3. A new module for using Alfresco.
Create this property file in "src/main/resources/properties/cmis.properties". (The "properties" folder should be created for this purpose).
1 2 3 4 5 6 7 8 | #5. ALFRESCO #5.1 URL to PLACE alfresco.URL= http://192.168.28.39:8080/alfresco/cmisatom #5.2 Credentials #adm..... alfresco.user=myuser alfresco.password=mypassword |
And here is a new class. the main class indicates how to read a file from Alfresco and save it to a file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | ackage ximodante.basic.utils.cmis; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.URL; import java.net.URLDecoder; import java.security.CodeSource; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.chemistry.opencmis.client.api.CmisObject; import org.apache.chemistry.opencmis.client.api.Document; import org.apache.chemistry.opencmis.client.api.ItemIterable; import org.apache.chemistry.opencmis.client.api.Repository; import org.apache.chemistry.opencmis.client.api.Session; import org.apache.chemistry.opencmis.client.api.SessionFactory; import org.apache.chemistry.opencmis.client.runtime.OperationContextImpl; import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; import org.apache.chemistry.opencmis.commons.SessionParameter; import org.apache.chemistry.opencmis.commons.data.ContentStream; import org.apache.chemistry.opencmis.commons.enums.BindingType; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; enum ExecutionTypeEnum { JAR,NO_JAR,WAR } public class CMISUtilsBis { /** * Get the main class for getting the jar * @return the class name * @see https://stackoverflow.com/a/36949543 * * DOES NOT WORK WITH GRADLE WAR (WEB) */ public static String getMainClassName() { StackTraceElement trace[] = Thread.currentThread().getStackTrace(); if (trace.length > 0) { for (int i=0; i<trace.length; i++) System.out.println("StackTrace class("+i+")="+trace[i].getClassName()); return trace[trace.length - 1].getClassName(); } return "Unknown"; } /** * Folder that contains jar file or folder that contains project folder * NOW NOT FAILS if the caller class is nor in the same jar in Gradle!!!!! * @return * @throws Exception */ public static String getJarContainingFolder() throws Exception { //Class<?> aClass = MethodHandles.lookup().lookupClass(); // Class<?> aClass =Class.forName(getMainClassName()); CodeSource codeSource = aClass.getProtectionDomain().getCodeSource(); File jarFile; if (codeSource.getLocation() != null) { jarFile = new File(codeSource.getLocation().toURI()); } else { // It is not a jar file String path = aClass.getResource(aClass.getSimpleName() + ".class").getPath(); String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!")); jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8"); jarFile = new File(jarFilePath); } String s = jarFile.getParentFile().getAbsolutePath(); System.out.println("S------>:" + s); if (s.endsWith(File.separator + "target")) { // Maven target directory for compiled classes s = s.substring(0, s.lastIndexOf(File.separator)); s = s.substring(0, s.lastIndexOf(File.separator)); } return s; } /** * NOW NOT FAILS IN GRADLE if you don't give a class * @param isExecutedFromJAR * @param filePath * @return * @throws Exception */ //public static String getRelativeResourceFile(boolean isExecutedFromJAR, String filePath) throws Exception { public static String getRelativeResourceFile(ExecutionTypeEnum execType, String filePath) throws Exception { String path=""; //System.out.println("TRY PATH="+Thread.currentThread().getContextClassLoader().getResource("").getPath()); switch (execType) { case JAR : path= getJarContainingFolder(); break; case NO_JAR : path= System.getProperty("user.dir") + File.separator + "src" + File.separator + "main" + File.separator + "resources"; break; case WAR: path = Thread.currentThread().getContextClassLoader().getResource("").getPath(); break; default: throw new Exception("invalid ExcecutionType ! -->" + execType); } System.out.println("GOT PATH="+path); path += File.separator + filePath; return path; } /** * Get properties form file in the resources/properties folder * @param execType * @param propName * @return * @throws Exception */ public static Properties getProperties(ExecutionTypeEnum execType, String propName) throws Exception { Properties props=new Properties(); String fileName=getRelativeResourceFile(execType, "properties"+File.separator+ propName+".properties"); props.load(new FileInputStream(fileName)); return props; } /** * Get a HashnMap with all the needed properties to access an Alfresco installation * @param props * @return */ public static Map<String, String> getCredentials(Properties props) { if (props==null) return null; String user=props.getProperty("alfresco.user"); String password=props.getProperty("alfresco.password"); String alfrescoURL=props.getProperty("alfresco.URL"); return getCredentials(user, password, alfrescoURL); } public static Map<String, String> getCredentials(String user, String password, String alfrescoURL) { if (user==null) return null; // 1. Create Map Map<String, String> parameters = new HashMap<String, String>(); // 2. user credentials parameters.put(SessionParameter.USER, user); parameters.put(SessionParameter.PASSWORD, password); // 3. connection settings parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); // Since Alfresco Version 4.xx on @ see https://stackoverflow.com/a/41601409/7704658 parameters.put(SessionParameter.ATOMPUB_URL,alfrescoURL); try { URL srvURL=new URL(alfrescoURL); String hostName=srvURL.getHost(); if (InetAddress.getByName(hostName).isReachable(5000)) { //if (NetUtils.isURLReachable(serverURL)) return parameters; /* int response=((HttpURLConnection)srvURL.openConnection()).getResponseCode(); if (response==HttpURLConnection.HTTP_OK || response==HttpURLConnection.HTTP_UNAUTHORIZED || response==HttpURLConnection.HTTP_FORBIDDEN ) return parameters; */ return parameters; } } catch (IOException e) { e.printStackTrace(); } return null; } /** * Gets a CMIS Session * @param CMISProps * @return * @throws Exception */ public static Session getCMISSession(Properties CMISProps) throws Exception { Map<String,String> mpCred=getCredentials(CMISProps); return getCMISSession(mpCred); } public static Session getCMISSession(String user, String password, String alfrescoURL) throws Exception { Map<String,String> mpCred=getCredentials(user, password, alfrescoURL); return getCMISSession(mpCred); } public static Session getCMISSession(Map<String,String> mpCredentials) throws Exception { Session CMISSession=null; if (mpCredentials!=null) { //2.2 Get session Factory SessionFactory gSession=getSessionFactory(); //2.3 Get repositories List<Repository>lRepos=getRepos(gSession, mpCredentials); //2.4. Create a session on the first repository CMISSession = lRepos.get(0).createSession(); //2.5. Get the root folder and print children //Folder rootFolder = CMISSession.getRootFolder(); // END CMIS DEFINITION } return CMISSession; } /** * Get a session factory element * @return */ public static SessionFactory getSessionFactory() { return SessionFactoryImpl.newInstance(); } /** * Get a list of all available repositories * @param sesFact * @param parameters * @return */ public static List<Repository> getRepos(SessionFactory sesFact, Map<String,String> parameters) { return sesFact.getRepositories(parameters); } /** * get a session for working on a repository * @param repo * @return */ public static Session getSessionFromRepo (Repository repo) { return repo.createSession(); } private static Document getDoc(Session session, String partialDocName, String nameOrId) throws IOException { Document document=null; if (nameOrId.trim().equalsIgnoreCase("name")) { ItemIterable<CmisObject> results = session.queryObjects("cmis:document", "cmis:name LIKE '%"+ partialDocName+ "%'", false, new OperationContextImpl()); document=(Document)results.iterator().next(); } else { //id //CmisObject cmisObject = this.session.getObject(partialDocName); document = (Document) session.getObject(partialDocName); //results= this.session.queryObjects("cmis:document", "cmis:objectId = '"+ partialDocName+ "'", false, new OperationContextImpl()); } return document; } /** * Saves an Alfresco document to new full file name and path * The document can be searched by name or id * @param partialDocName or id * @param fullFileName * @param nameOrId * @throws IOException */ public static void saveDocumentToFile(Session session, String partialDocName, String fullFileName, String nameOrId) throws IOException { Document document=getDoc(session,partialDocName, nameOrId); System.out.println("----Name:" + document.getName()); System.out.println("----Id:" + document.getId()); System.out.println("----URL:" + document.getContentUrl()); ContentStream contentStream = document.getContentStream(); InputStream stream = contentStream.getStream(); //File targetFile = new File("src/main/resources/targetFile.tmp"); if (fullFileName==null || fullFileName.length()==0) fullFileName="src/main/resources/"+document.getName(); File targetFile = new File(fullFileName); FileUtils.copyInputStreamToFile(stream, targetFile); } /** * Saves several Alfresco documents to a folder. You search them by partial name or id * @param partialDocName or id * @param folderName * @param nameOrId * @throws IOException */ public static void saveDocumentsToFile(Session session, String partialDocName, String folderName, String nameOrId) throws IOException { if (folderName==null || folderName.length()==0) folderName="src/main/resources"; Document document=getDoc(session,partialDocName, nameOrId); //for(CmisObject doc: results) { System.out.println("87s--->Name:" + document.getName()); System.out.println("87s--->URL:" + document.getContentUrl()); System.out.println("87s--->description:" + document.getDescription()); System.out.println("id="+ document.getId()); System.out.println("--------------------------"); ContentStream contentStream = document.getContentStream(); InputStream stream = contentStream.getStream(); String fileName=folderName+ "/" + document.getName(); File targetFile = new File(fileName); FileUtils.copyInputStreamToFile(stream, targetFile); //} /* CmisObject cmisObject = this.session.getObject("workspace://SpacesStore/e58d9df1-89bb-401b-85fc-e9a7a6fa17e6"); if (cmisObject instanceof Document) { Document document1 = (Document) cmisObject; System.out.println("id1="+ document1.getId()); System.out.println("description1=" + document1.getDescription()); System.out.println("name1=" + document1.getName()); System.out.println("name1=" + document1.getContentUrl()); } */ } /** * Get a document from CMIS, and saves it renaming the base name to "fileName" and conserving its extension * @param partialDocName or id * @param baseFileName full file name and path without extension * @param nameOrId (find by partial name or id) * @throws IOException * */ public static String saveDocumentToFileWithExtension(Session session, String partialDocName, String baseFileName, String nameOrId) throws IOException { Document document=getDoc(session,partialDocName, nameOrId); String extension= FilenameUtils.getExtension(document.getName()).toLowerCase(); /* System.out.println("----Name:" + document.getName()); System.out.println("----Id:" + document.getId()); System.out.println("----URL:" + document.getContentUrl()); */ ContentStream contentStream = document.getContentStream(); InputStream stream = contentStream.getStream(); //File targetFile = new File("src/main/resources/targetFile.tmp"); if (baseFileName==null || baseFileName.length()==0) baseFileName="src/main/resources/"+document.getName(); else baseFileName=baseFileName+"."+extension; File targetFile = new File(baseFileName); FileUtils.copyInputStreamToFile(stream, targetFile); return baseFileName; } /** * Return a contentStream of the document * @param session * @param partialDocName * @param nameOrId * @return * @throws IOException */ private static ContentStream getContentStreamDocument(Session session,String partialDocName, String nameOrId) throws IOException { Document document=getDoc(session,partialDocName, nameOrId); System.out.println("cmis-partialDocName="+partialDocName + " cmis-nameOrId=" + nameOrId); /* System.out.println("----Name:" + document.getName()); System.out.println("----Id:" + document.getId()); System.out.println("----URL:" + document.getContentUrl()); */ return document.getContentStream(); } /** * Return an input stream of the document in the CMIS * @param session * @param partialDocName * @param nameOrId * @return * @throws IOException */ public static InputStream getContentInputStreamDocument(Session session,String partialDocName, String nameOrId) throws IOException { return getContentStreamDocument(session,partialDocName, nameOrId).getStream(); } public static void main(String[] args) throws Exception { Properties CMISProps =getProperties(ExecutionTypeEnum.NO_JAR, "cmis"); Session CMISSession = getCMISSession(CMISProps); try { CMISUtilsBis.saveDocumentsToFile(CMISSession, "tti__4737f32a-493c-4803-b657-60303da009c0" , "/home/ximo/KKK", "name"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } |
4. Accessing Alfresco using HTTP
Referencing alfresco-content-services-blog, you can use HTTP for downloading a document by its "id" from alfresco (in this case the id is "123456xy"
http://myserver:8080/alfresco/service/api/node/content/workspace/SpacesStore/123456xy