miércoles, 20 de marzo de 2019

1. Create a Maven Project with Eclipse

1. Create a Maven project with Eclipse (and arrange the pom.xml file)


File-New-Maven project


Select Create a simple project (skip archetype selection)
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:

  1. Create a HashMap 
  2. Feed the map with: user, password, binding protocol and Alfresco server URL. Note the special URL to access the server.
  3. Get a SessionFactory
  4. Use the SessionFactory to select a repository (usually the first one)
  5. 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