View Javadoc

1   /**
2    * Copyright (C) 2005-2009 Alfresco Software Limited.
3    *
4    * This file is part of the Spring Surf Extension project.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.springframework.extensions.webscripts.connector;
20  
21  import java.io.BufferedReader;
22  import java.io.File;
23  import java.io.FileReader;
24  import java.io.FileWriter;
25  import java.io.IOException;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.dom4j.Document;
32  import org.dom4j.Element;
33  import org.dom4j.io.OutputFormat;
34  import org.dom4j.io.XMLWriter;
35  import org.springframework.extensions.config.RemoteConfigElement.EndpointDescriptor;
36  import org.springframework.extensions.surf.util.StringBuilderWriter;
37  
38  /**
39   * A basic implementation of a persistent credential vault where
40   * credentials are stored in XML on disk.
41   * 
42   * Note:  You should never use anything like this in production.  Rather,
43   * it is suitable for test suites (locally and within test frameworks).
44   * 
45   * It also is a useful example of another kind of credential vault
46   * 
47   * @author muzquiano
48   */
49  public class XMLCredentialVault extends AbstractPersistentCredentialVault
50  {
51      private static Log logger = LogFactory.getLog(XMLCredentialVault.class);
52      
53      protected String location;
54      
55      /**
56       * Instantiates a new XML credential vault.
57       * 
58       * @param id the id
59       */
60      public XMLCredentialVault(String id)
61      {
62          super(id);
63      }
64          
65      public void setLocation(String location)
66      {
67          this.location = location;
68      }
69      
70      public String getLocation()
71      {
72          return this.location;
73      }
74                  
75      /* (non-Javadoc)
76       * @see org.alfresco.connector.CredentialVault#load()
77       */
78      public boolean load()
79      {
80          boolean success = false;
81          
82          File file = new File(getLocation() + "/" + this.id + ".xml");
83          if(file.exists())
84          {
85              StringBuilder contents = new StringBuilder();
86              try 
87              {
88                  BufferedReader input = new BufferedReader(new FileReader(file));
89                  try
90                  {
91                      String line = null;
92      
93                      while (( line = input.readLine()) != null)
94                      {
95                          contents.append(line);
96                          contents.append(System.getProperty("line.separator"));
97                      }
98                      
99                      // get the xml
100                     String xml = contents.toString();
101                     
102                     // deserialize
103                     deserialize(xml);
104                     
105                     // mark that the load was successful
106                     success = true;
107                 }
108                 finally 
109                 {
110                     input.close();
111                 }
112             }
113             catch (IOException ex)
114             {
115                 ex.printStackTrace();
116             }   
117         }
118         else
119         {
120             if(logger.isDebugEnabled())
121             {
122                 logger.debug("Unable to load XML Credential Vault");
123                 logger.debug("Not found: " + file.getAbsolutePath());
124             }
125         }
126         
127         return success;
128     }
129 
130     /* (non-Javadoc)
131      * @see org.alfresco.connector.CredentialVault#save()
132      */
133     public boolean save()
134     {
135         boolean success = false;
136         
137         String xml = serialize();
138         
139         File file = new File(getLocation() + "/" + this.id + ".xml");
140         if(file.exists())
141         {
142             file.delete();
143         }
144         
145         FileWriter fw = null;
146         try
147         {
148             fw = new FileWriter(file, true);
149             fw.write(xml);
150             
151             // mark that the save was successful
152             success = true;
153         }
154         catch(Exception ex)
155         {
156             ex.printStackTrace();
157         }
158         finally
159         {
160             if(fw != null)
161             {
162                 try { fw.close(); } catch(Exception ex) { }
163             }
164         }
165         
166         return success;
167     }
168         
169     /**
170      * Serialize.
171      * 
172      * @return the string
173      */
174     protected String serialize()
175     {
176         Element rootElement = org.dom4j.DocumentHelper.createElement("vault");
177         rootElement.addAttribute("id", this.id);
178         
179         Document d = org.dom4j.DocumentHelper.createDocument(rootElement);
180         
181         // walk through all of the endpoints
182         Iterator it = credentialsMap.keySet().iterator();
183         while(it.hasNext())
184         {
185             String endpointId = (String) it.next();
186             
187             EndpointDescriptor descriptor = getRemoteConfig().getEndpointDescriptor(endpointId);
188             if(descriptor.getPersistent())
189             {    
190                 // store it
191                 Element endpointElement = rootElement.addElement("endpoint");
192                 endpointElement.addAttribute("id", endpointId);
193                             
194                 Credentials credentials = retrieve(endpointId);
195     
196                 String[] keys = credentials.getPropertyKeys();
197                 for(int i = 0; i < keys.length; i++)
198                 {
199                     String value = (String) credentials.getProperty(keys[i]);
200                     
201                     Element credentialElement = endpointElement.addElement("credential");
202                     credentialElement.addAttribute("id", keys[i]);
203                     credentialElement.setText(value);
204                 }
205             }
206         }
207 
208         return toXML(d, true);
209     }
210     
211     /**
212      * Deserialize.
213      * 
214      * @param xml the xml
215      */
216     protected void deserialize(String xml)
217     {
218         // reset the map
219         //credentialsMap = new HashMap<String, Credentials>(16, 1.0f);
220         
221         // doc
222         Document d = null;
223         try
224         {
225             d = org.dom4j.DocumentHelper.parseText(xml);
226             
227             Element rootElement = d.getRootElement();
228             this.id = rootElement.attributeValue("id");
229             
230             List endpoints = rootElement.elements("endpoint");
231             for(int i = 0; i < endpoints.size(); i++)
232             {
233                 Element endpointElement = (Element) endpoints.get(i);
234                 String endpointId = endpointElement.attributeValue("id");
235                 
236                 // check whether this endpoint id is a persistent one
237                 EndpointDescriptor descriptor = getRemoteConfig().getEndpointDescriptor(endpointId);
238                 if(descriptor.getPersistent())
239                 {                
240                     // create the credentials object
241                     Credentials credz = newCredentials(endpointId);
242                     
243                     // populate
244                     List credentialsList = endpointElement.elements("credential");
245                     for(int k = 0; k < credentialsList.size(); k++)
246                     {
247                         Element credential = (Element) credentialsList.get(k);
248                         
249                         String credentialId = credential.attributeValue("id");
250                         String credentialValue = credential.getTextTrim();
251                         
252                         credz.setProperty(credentialId, credentialValue);
253                     }
254                 
255                     // set onto map
256                     store(credz);
257                 }
258             }
259         }
260         catch(Exception ex)
261         {
262             ex.printStackTrace();
263         }
264     }
265     
266     /* (non-Javadoc)
267      * @see java.lang.Object#toString()
268      */
269     @Override
270     public String toString()
271     {
272         return "XMLCredentialVault - " + location;
273     }        
274     
275     /**
276      * Converts the document to XML.  The pretty switch can be used to produce
277      * human readable, or pretty, XML.
278      * 
279      * @param document the document
280      * @param pretty whether to produce human readable XML
281      * 
282      * @return the string
283      */
284     public static String toXML(Document document, boolean pretty)
285     {
286         String xml = null;
287         
288         if (pretty)
289         {
290             OutputFormat format = OutputFormat.createPrettyPrint();
291             format.setSuppressDeclaration(false);
292 
293             StringBuilderWriter writer = new StringBuilderWriter(256);
294             XMLWriter xmlWriter = new XMLWriter(writer, format);
295             try
296             {
297                 xmlWriter.write(document);
298                 xmlWriter.flush();
299                 xml = writer.toString();
300             }
301             catch (IOException ioe)
302             {
303                 /**
304                  * If this exception occurs, we'll log a note to the console
305                  * and then proceed to serialze the old fashioned way.
306                  */
307                 logger.debug(ioe);
308             }
309         }
310 
311         /**
312          * If the XML wasn't created already, we'll serialize the
313          * standard way.
314          */
315         if (xml == null)
316         {
317             xml = document.asXML();
318         }
319         
320         return xml;
321     }
322     
323 }