001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2013-02-21 19:20:44 +0000 (Thu, 21 Feb 2013) $' 
007 * '$Revision: 31475 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler.objectmanager.repository;
031
032import java.io.File;
033import java.io.FileInputStream;
034import java.io.FileNotFoundException;
035import java.io.FileOutputStream;
036import java.io.IOException;
037import java.io.InputStream;
038import java.io.ObjectInput;
039import java.io.ObjectInputStream;
040import java.io.ObjectOutputStream;
041import java.io.OutputStream;
042import java.lang.reflect.Constructor;
043import java.util.Iterator;
044import java.util.List;
045import java.util.Vector;
046
047import org.apache.commons.logging.Log;
048import org.apache.commons.logging.LogFactory;
049import org.kepler.configuration.ConfigurationManager;
050import org.kepler.configuration.ConfigurationProperty;
051import org.kepler.util.DotKeplerManager;
052
053/**
054 * This class provides functionality to upload and retrieve objects from the
055 * Ecogrid repository for Kepler actor/kar objects.
056 * 
057 * @author Chad Berkley
058 */
059public class RepositoryManager {
060        private static final Log log = LogFactory.getLog(RepositoryManager.class.getName());
061        private static final boolean isDebugging = log.isDebugEnabled();
062
063        public static final String RESOURCEBUNDLE_DIR = "ptolemy/configs/kepler";
064
065        /**
066         * The singleton instance.
067         */
068        private static RepositoryManager _manager;
069
070        /**
071         * The main vector where repository information is stored.
072         */
073        private Vector<Repository> _repositoryVector = new Vector<Repository>();
074
075        /**
076         * The name of the repository to use for saving KARs to.
077         */
078        private String _saveRepositoryName;
079
080        /**
081         * The actual repository object for saving KARs to.
082         */
083        private Repository _saveRepository;
084
085        /**
086         * The file in the module readwrite area where we'll save the name of the
087         * user selected remote repository to save KAR files to.
088         */
089        private String _remoteSaveRepoFileName;
090
091        /**
092         * default constructor
093         */
094        public RepositoryManager() throws IOException, Exception {
095                if (isDebugging)
096                        log.debug("RepositoryManager()");
097
098                // Set up file name for storing default local save directory
099                File modDir = DotKeplerManager.getInstance()
100                                .getTransientModuleDirectory("util");
101                if (modDir != null) {
102                        _remoteSaveRepoFileName = modDir.toString();
103                } else {
104                        _remoteSaveRepoFileName = System.getProperty("KEPLER");
105                }
106                if (!_remoteSaveRepoFileName.endsWith(File.separator)) {
107                        _remoteSaveRepoFileName += File.separator;
108                }
109                _remoteSaveRepoFileName += "RemoteSaveRepository";
110
111                ConfigurationProperty prop = ConfigurationManager.getInstance()
112                                .getProperty(ConfigurationManager.getModule("repository"));
113                List reposList = prop.getProperties("repository");
114                for (int i = 0; i < reposList.size(); i++) {
115                        ConfigurationProperty cp = (ConfigurationProperty) reposList.get(i);
116                        String name = cp.getProperty("name").getValue();
117
118                        log.info("adding repository " + name);
119
120                        String repository = cp.getProperty("repository").getValue();
121                        String putPath = cp.getProperty("putpath").getValue();
122                        String authProtocol = cp.getProperty("authprotocol").getValue();
123                        String authDomain = cp.getProperty("authdomain").getValue();
124                        String lsidPath = cp.getProperty("lsidpath").getValue();
125                        String queryPath = cp.getProperty("querypath").getValue();
126                        String authenticatedQueryPath = cp.getProperty("authenticatedquerypath").getValue();
127                        String registry = cp.getProperty("registrypath").getValue();
128                        String registryauth = cp.getProperty("registryauth").getValue();
129                        String repClass = cp.getProperty("class").getValue();
130                        String lsidAuthority = cp.getProperty("lsidAuthority").getValue();
131                        String searchRepository = cp.getProperty("searchRepository").getValue();
132                        ConfigurationProperty authorizationPathProperty = cp.getProperty("authorizationPath");
133                        String authorizationPath = null;
134                        if (authorizationPathProperty == null)
135                        {
136                          log.warn("The repository "+name+ " doesn't have the authorization path. "+
137                           " Please modify the repository configuration file");
138                          continue;
139                        }
140                        else
141                        {
142                          authorizationPath= authorizationPathProperty.getValue();
143                        }
144                        
145                        //System.out.println("searchRepository: " + searchRepository);
146                        // create the repository with the given class using reflections
147                        String[] s = new String[12];
148                        s[0] = name;
149                        s[1] = repository;
150                        s[2] = putPath;
151                        s[3] = authDomain;
152                        s[4] = lsidPath;
153                        s[5] = queryPath;
154                        s[6] = authenticatedQueryPath;
155                        s[7] = authorizationPath;
156                        s[8] = registry;
157                        s[9] = registryauth;
158                        s[10] = authProtocol;
159                        s[11] = lsidAuthority;
160                        Repository r = createInstance(Class.forName(repClass), s);
161                        if(searchRepository != null && (searchRepository.equals("true") || searchRepository.equals("TRUE")))
162                        {
163                          r.setIncludeInSearch(true);
164                        }
165                        else
166                        {
167                          r.setIncludeInSearch(false);
168                        }
169                        _repositoryVector.addElement(r);
170                }
171
172                // set the default save repository
173                // first check the configuration to see if one is defined there
174                /*
175                 * if(Configuration.configurations().iterator().hasNext()) {
176                 * Configuration config =
177                 * (Configuration)Configuration.configurations().iterator().next(); }
178                 * 
179                 * String saveRepositoryName = null; StringAttribute sa =
180                 * (StringAttribute)config.getAttribute("_repository"); if (sa != null)
181                 * { saveRepositoryName = sa.getExpression(); //use this override
182                 * setSaveRepository(getRepository(saveRepositoryName)); }
183                 */
184                // do we have an old one?
185                initRemoteSaveRepo();
186        }
187
188        /**
189         * First we check to see if there is a configuration file containing the
190         * name of the default remote save repository. Then we check the
191         * configuration file.
192         */
193        private void initRemoteSaveRepo() {
194                if (isDebugging)
195                        log.debug("initRemoteSaveRepo()");
196                File remoteSaveRepoFile = new File(_remoteSaveRepoFileName);
197
198                if (!remoteSaveRepoFile.exists()) {
199                        setSaveRepository(null);
200                } else {
201                        if (isDebugging) {
202                                log.debug("remoteSaveRepo exists: "
203                                                + remoteSaveRepoFile.toString());
204                        }
205
206                        try {
207                                InputStream is = null;
208                                ObjectInput oi = null;
209                                try {
210                                        is = new FileInputStream(remoteSaveRepoFile);
211                                        oi = new ObjectInputStream(is);
212                                        Object newObj = oi.readObject();
213                                
214                                        String repoName = (String) newObj;
215                                        Repository saveRepo = getRepository(repoName);
216                                        if (saveRepo != null) {
217                                                setSaveRepository(saveRepo);
218                                        }
219
220                                        return;
221
222                                } finally {
223                                        if(oi != null) {
224                                                oi.close();
225                                        }
226                                        if(is != null) {
227                                                is.close();
228                                        }
229                                }
230
231                        } catch (Exception e1) {
232                                // problem reading file, try to delete it
233                                log.warn("Exception while reading localSaveRepoFile: "
234                                                + e1.getMessage());
235                                try {
236                                        remoteSaveRepoFile.delete();
237                                } catch (Exception e2) {
238                                        log.warn("Unable to delete localSaveRepoFile: "
239                                                        + e2.getMessage());
240                                }
241                        }
242                }
243
244        }
245
246        /**
247         * Returns a singleton instance of this class
248         */
249        public static RepositoryManager getInstance() throws IOException, Exception {
250                if (_manager == null) {
251                        _manager = new RepositoryManager();
252                }
253                return _manager;
254        }
255
256        /**
257         * return the list of repositories
258         */
259        public Iterator<Repository> repositoryList() {
260                return _repositoryVector.iterator();
261        }
262
263        /**
264         * return the list of repositories
265         */
266        public Vector<Repository> getRepositories() {
267                return _repositoryVector;
268        }
269
270        public void setSearchNone() {
271                for (Repository r : getRepositories()) {
272                        r.setIncludeInSearch(false);
273                }
274        }
275
276        /**
277         * returns the repository with the given name. if it doesn't exist, this
278         * method returns null.
279         */
280        public Repository getRepository(String name) {
281                if (isDebugging)
282                        log
283                                        .debug("getRepository(" + name + ") "
284                                                        + _repositoryVector.size());
285
286                if (name == null)
287                        return null;
288
289                for (int i = 0; i < _repositoryVector.size(); i++) {
290                        Repository r = (Repository) _repositoryVector.elementAt(i);
291                        if (r != null) {
292                                if (isDebugging)
293                                        log.debug(r.getName());
294                                if (r.getName().trim().equals(name.trim())) {
295                                        return r;
296                                }
297                        }
298                }
299                return null;
300        }
301
302        /**
303         * return the repository that is currently marked as the save repository
304         */
305        public Repository getSaveRepository() {
306                return _saveRepository;
307        }
308
309        /**
310         * set the repository that should be saved to.
311         */
312        public void setSaveRepository(Repository rep) {
313                if (rep == null) {
314                        if (isDebugging)
315                                log.debug("setSaveRepository(null)");
316                        _saveRepository = null;
317                        _saveRepositoryName = null;
318                } else {
319                        if (isDebugging)
320                                log.debug("setSaveRepository(" + rep.getName() + ")");
321                        _saveRepository = rep;
322                        _saveRepositoryName = rep.getName();
323                }
324                serializeRemoteSaveRepo();
325        }
326
327        /**
328         * creates and instance of a repository
329         * 
330         *@param newClass
331         *@param arguments
332         *@return Repository
333         */
334        private Repository createInstance(Class newClass, Object[] arguments)
335                        throws Exception {
336                Constructor[] constructors = newClass.getConstructors();
337                for (int i = 0; i < constructors.length; i++) {
338                        Constructor constructor = constructors[i];
339                        Class[] parameterTypes = constructor.getParameterTypes();
340
341                        for (int j = 0; j < parameterTypes.length; j++) {
342                                Class c = parameterTypes[j];
343                        }
344
345                        if (parameterTypes.length != arguments.length) {
346                                continue;
347                        }
348
349                        boolean match = true;
350
351                        for (int j = 0; j < parameterTypes.length; j++) {
352                                if (!(parameterTypes[j].isInstance(arguments[j]))) {
353                                        match = false;
354                                        break;
355                                }
356                        }
357
358                        if (match) {
359                                Repository newRepository = (Repository) constructor
360                                                .newInstance(arguments);
361                                return newRepository;
362                        }
363                }
364
365                // If we get here, then there is no matching constructor.
366                // Generate a StringBuffer containing what we were looking for.
367                StringBuffer argumentBuffer = new StringBuffer();
368
369                for (int i = 0; i < arguments.length; i++) {
370                        argumentBuffer.append(arguments[i].getClass() + " = \""
371                                        + arguments[i].toString() + "\"");
372
373                        if (i < (arguments.length - 1)) {
374                                argumentBuffer.append(", ");
375                        }
376                }
377
378                throw new Exception("Cannot find a suitable constructor ("
379                                + arguments.length + " args) (" + argumentBuffer + ") for '"
380                                + newClass.getName() + "'");
381        }
382
383        /**
384         * Serialize the remote save repository name to a file on disk so it can be
385         * loaded the next time Kepler starts.
386         */
387        private void serializeRemoteSaveRepo() {
388                if (isDebugging)
389                        log.debug("serializeRemoteSaveRepo()");
390
391                File remoteSaveRepoFile = new File(_remoteSaveRepoFileName);
392                if (remoteSaveRepoFile.exists()) {
393                        if (isDebugging)
394                                log.debug("delete " + remoteSaveRepoFile);
395                        remoteSaveRepoFile.delete();
396                }
397                if (_saveRepositoryName != null) {
398                        try {
399                                OutputStream os = new FileOutputStream(remoteSaveRepoFile);
400                                ObjectOutputStream oos = null;
401                                try {
402                                    oos = new ObjectOutputStream(os);
403                                oos.writeObject(_saveRepositoryName);
404                                oos.flush();
405                                if (isDebugging) {
406                                        log.debug("wrote " + remoteSaveRepoFile);
407                                }
408                                } finally {
409                                    if(oos != null) {
410                                        oos.close();
411                                    }
412                                }
413                        } catch (FileNotFoundException e) {
414                                e.printStackTrace();
415                        } catch (IOException e) {
416                                e.printStackTrace();
417                        }
418                }
419        }
420}