// // Copyright 2010 Cinch Logic Pty Ltd. // // http://www.chililog.com // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package org.chililog.server.data; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.bson.types.ObjectId; import org.chililog.server.common.ChiliLogException; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MongoException; /** * Singleton to manage our access to repository configuration documents in our mongoDB * * @author vibul * */ public class RepositoryConfigController extends Controller { public static final String MONGODB_COLLECTION_NAME = "repo"; /** * Returns the singleton instance for this class */ public static RepositoryConfigController getInstance() { return SingletonHolder.INSTANCE; } /** * SingletonHolder is loaded on the first execution of Singleton.getInstance() or the first access to * SingletonHolder.INSTANCE, not before. * * @see http://en.wikipedia.org/wiki/Singleton_pattern */ private static class SingletonHolder { public static final RepositoryConfigController INSTANCE = new RepositoryConfigController(); } /** * <p> * Singleton constructor * </p> */ private RepositoryConfigController() { return; } /** * Returns the name of the mongoDB collection for this business object */ @Override protected String getDBCollectionName() { return MONGODB_COLLECTION_NAME; } /** * Retrieves the specified repository by its id * * @param db * mongoDB connection * @param id * unique id for the document stored in mongoDB * @return code>RepositoryInfoBO</code> representing the repository * @throws ChiliLogException * if not found or database error */ public RepositoryConfigBO get(DB db, ObjectId id) throws ChiliLogException { RepositoryConfigBO o = tryGet(db, id); if (o == null) { throw new ChiliLogException(Strings.REPO_INFO_NOT_FOUND_ERROR, id.toString()); } return o; } /** * Tries to retrieve the specified repository by its id. If not found, null is returned. * * @param db * mongoDB connection * @param id * unique id for the document stored in mongoDB * @return <code>RepositoryInfoBO</code> representing the repository or null if repository is not found * @throws ChiliLogException * if database or data error */ public RepositoryConfigBO tryGet(DB db, ObjectId id) throws ChiliLogException { try { if (db == null) { throw new IllegalArgumentException("db cannot be null"); } if (id == null) { throw new IllegalArgumentException("id cannot be null"); } DBCollection coll = db.getCollection(MONGODB_COLLECTION_NAME); BasicDBObject condition = new BasicDBObject(); condition.put(BO.DOCUMENT_ID_FIELD_NAME, id); DBObject dbo = coll.findOne(condition); if (dbo == null) { return null; } return new RepositoryConfigBO(dbo); } catch (MongoException ex) { throw new ChiliLogException(ex, Strings.MONGODB_QUERY_ERROR, ex.getMessage()); } } /** * Retrieves the specified repository by its name * * @param db * mongoDB connection * @param name * name of the repository to retrieve * @return code>RepositoryInfoBO</code> representing the repository * @throws ChiliLogException * if not found or database error */ public RepositoryConfigBO getByName(DB db, String name) throws ChiliLogException { RepositoryConfigBO o = tryGetByName(db, name); if (o == null) { throw new ChiliLogException(Strings.REPO_INFO_NOT_FOUND_ERROR, name); } return o; } /** * Tries to retrieve the specified repository by its name. If not found, null is returned. * * @param db * mongoDB connection * @param name * name of repository to retrieve * @return <code>RepositoryInfoBO</code> representing the repository or null if repository is not found * @throws ChiliLogException * if database or data error */ public RepositoryConfigBO tryGetByName(DB db, String name) throws ChiliLogException { try { if (db == null) { throw new IllegalArgumentException("db cannot be null"); } if (StringUtils.isBlank(name)) { throw new IllegalArgumentException("name cannot be blank"); } DBCollection coll = db.getCollection(MONGODB_COLLECTION_NAME); BasicDBObject condition = new BasicDBObject(); condition.put(RepositoryConfigBO.NAME_FIELD_NAME, name); DBObject dbo = coll.findOne(condition); if (dbo == null) { return null; } return new RepositoryConfigBO(dbo); } catch (MongoException ex) { throw new ChiliLogException(ex, Strings.MONGODB_QUERY_ERROR, ex.getMessage()); } } /** * Get a list of all users * * @param db * mongoDB connection * @param criteria * criteria to filter users * @return List of users matching the specified criteria * @throws ChiliLogException * if database or data error */ public ArrayList<RepositoryConfigBO> getList(DB db, RepositoryConfigListCriteria criteria) throws ChiliLogException { DBCollection coll = db.getCollection(MONGODB_COLLECTION_NAME); // Filter BasicDBObject condition = new BasicDBObject(); if (!StringUtils.isBlank(criteria.getNamePattern())) { Pattern pattern = Pattern.compile(criteria.getNamePattern()); condition.put(RepositoryConfigBO.NAME_FIELD_NAME, pattern); } if (criteria.getNameRestrictions() != null && criteria.getNameRestrictions().length > 0) { condition.put(RepositoryConfigBO.NAME_FIELD_NAME, new BasicDBObject("$in", criteria.getNameRestrictions())); } // Order DBObject orderBy = new BasicDBObject(); orderBy.put(RepositoryConfigBO.NAME_FIELD_NAME, 1); // Get matching records int recordsPerPage = criteria.getRecordsPerPage(); int skipDocumentCount = (criteria.getStartPage() - 1) * recordsPerPage; DBCursor cur = coll.find(condition).skip(skipDocumentCount).limit(recordsPerPage).sort(orderBy); ArrayList<RepositoryConfigBO> list = new ArrayList<RepositoryConfigBO>(); while (cur.hasNext()) { DBObject dbo = cur.next(); list.add(new RepositoryConfigBO(dbo)); } // Do page count by executing query again if (criteria.getDoPageCount()) { int documentCount = coll.find(condition).count(); criteria.calculatePageCount(documentCount); } return list; } /** * Saves the repository into mongoDB * * @param db * MongoDb connection * @param repoConfig * Repository configuration to save * @throws ChiliLogException * if there are errors */ public void save(DB db, RepositoryConfigBO repoConfig) throws ChiliLogException { // Validate unique name DBCollection coll = db.getCollection(MONGODB_COLLECTION_NAME); BasicDBObject condition = new BasicDBObject(); condition.put(RepositoryConfigBO.NAME_FIELD_NAME, repoConfig.getName()); if (repoConfig.isExistingRecord()) { condition.put(BO.DOCUMENT_ID_FIELD_NAME, new BasicDBObject("$ne", repoConfig.getDocumentID())); } long i = coll.getCount(condition); if (i > 0) { throw new ChiliLogException(Strings.REPO_INFO_DUPLICATE_NAME_ERROR, repoConfig.getName()); } // Validate unique parser names for (RepositoryParserConfigBO p : repoConfig.getParsers()) { String parserName = p.getName(); int pCount = 0; for (RepositoryParserConfigBO p2 : repoConfig.getParsers()) { if (p2.getName().equals(parserName)) { pCount++; } } if (pCount != 1) { throw new ChiliLogException(Strings.REPO_INFO_DUPLICATE_PARSER_NAME_ERROR, parserName, repoConfig.getName()); } // Validate unique field names per parser for (RepositoryFieldConfigBO f : p.getFields()) { String fieldName = f.getName(); int count = 0; for (RepositoryFieldConfigBO f2 : p.getFields()) { if (f2.getName().equals(fieldName)) { count++; } } if (count != 1) { throw new ChiliLogException(Strings.REPO_INFO_DUPLICATE_FIELD_NAME_ERROR, fieldName, parserName, repoConfig.getName()); } } } // Save it super.save(db, repoConfig); // Add repository and index createIndexes(db); } /** * Creates the required repository index * * @param db * Database connection */ private void createIndexes(DB db) { DBCollection col = db.getCollection(this.getDBCollectionName()); List<DBObject> indexes = col.getIndexInfo(); boolean found = false; for (DBObject idx : indexes) { if (idx.get("name").equals("keyword_ts_index")) { found = true; break; } } if (!found) { BasicDBObject keys = new BasicDBObject(); keys.put(RepositoryEntryBO.KEYWORDS_FIELD_NAME, 1); keys.put(RepositoryEntryBO.TIMESTAMP_FIELD_NAME, 1); col.ensureIndex(keys, "keyword_ts_index"); } } /** * Removes the specified repository from mongoDB * * @param db * MongoDb connection * @param repoConfig * User to remove * @throws ChiliLogException * if there are errors */ public void remove(DB db, RepositoryConfigBO repoConfig) throws ChiliLogException { super.remove(db, repoConfig); } }