0001: /*
0002: * The contents of this file are subject to the
0003: * Mozilla Public License Version 1.1 (the "License");
0004: * you may not use this file except in compliance with the License.
0005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
0006: *
0007: * Software distributed under the License is distributed on an "AS IS"
0008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
0009: * See the License for the specific language governing rights and
0010: * limitations under the License.
0011: *
0012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
0013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
0014: *
0015: * All Rights Reserved.
0016: *
0017: * Contributor(s):
0018: */
0019: package org.openharmonise.rm.resources.content;
0020:
0021: import java.io.*;
0022: import java.sql.*;
0023: import java.util.*;
0024: import java.util.logging.*;
0025:
0026: import org.openharmonise.commons.cache.CacheException;
0027: import org.openharmonise.commons.dsi.*;
0028: import org.openharmonise.commons.dsi.dml.*;
0029: import org.openharmonise.commons.net.MimeTypeMapping;
0030: import org.openharmonise.rm.*;
0031: import org.openharmonise.rm.config.*;
0032: import org.openharmonise.rm.dsi.ColumnRefCache;
0033: import org.openharmonise.rm.publishing.*;
0034: import org.openharmonise.rm.resources.AbstractChildObject;
0035: import org.openharmonise.rm.resources.lifecycle.*;
0036: import org.w3c.dom.*;
0037:
0038: /**
0039: * The <code>Asset</code> class represents Harmonise resources which
0040: * reside on the local file system instead of in the database.
0041: *
0042: * @author Michael Bell
0043: * @version $Revision: 1.9 $
0044: *
0045: */
0046: public class Asset extends AbstractChildObject implements Publishable,
0047: Editable, Cloneable, Comparable {
0048:
0049: /**
0050: * String constant which is the name of the config property for detailing
0051: * what the webapp uri for assets is
0052: */
0053: private static final String PNAME_ASSET_WEBAPP_URI = "ASSET_WEBAPP_URI";
0054: /**
0055: * String constant which linking content types begin with
0056: */
0057: private static final String TXT_LINK = "link";
0058:
0059: /**
0060: * String constant which mime types of text resources begin with
0061: */
0062: private static final String TXT_TEXT = "text";
0063:
0064: //XML constants
0065: /**
0066: * The <code>Asset</code> tag name
0067: */
0068: public static final String TAG_ASSET = "Asset";
0069:
0070: /**
0071: * The URI tag name
0072: */
0073: public static final String TAG_URI = "URI";
0074:
0075: public static final String TAG_CONTENT_TYPE = "ContentType";
0076:
0077: //DB constants
0078: /**
0079: * The <code>Asset</code> database table name
0080: */
0081: protected static final String TBL_ASSET = "asset";
0082:
0083: /**
0084: * The URI database column name
0085: */
0086: protected static final String CLMN_URI = "content";
0087:
0088: /**
0089: * The mime type database column name
0090: */
0091: protected static final String CLMN_MIME_TYPE = "mime_type";
0092:
0093: /**
0094: * The site url configuration parameter name
0095: */
0096: static final String PNAME_SITE_URL = "SITE_URL";
0097:
0098: /**
0099: * The configuration parameter name whose associated value specifies
0100: * the file system directory to be used as the root of the asset store
0101: */
0102: public static final String PNAME_ASSET_ROOT_FILEPATH = "ASSET_ROOT";
0103:
0104: /**
0105: * The mime type of this <code>Asset</code>
0106: */
0107: protected String m_sContentType = null;
0108:
0109: /**
0110: * The URI or file path of this <code>Asset</code>
0111: */
0112: protected String m_sURI = null;
0113:
0114: /**
0115: * <code>boolean</code> flag which indicates whether the content/URI has been changed
0116: */
0117: private boolean m_bIsContentChanged = false;
0118:
0119: /**
0120: * Logger for this class
0121: */
0122: private static final Logger m_logger = Logger.getLogger(Asset.class
0123: .getName());
0124:
0125: /**
0126: * Constructs a new or anonymous instance without an interface
0127: * to the database
0128: */
0129: public Asset() {
0130: super ();
0131: }
0132:
0133: /**
0134: * Standard constructor for a new or anonymous resource.
0135: *
0136: * @param dbintrf the data store to register
0137: */
0138: public Asset(AbstractDataStoreInterface dbintrf) {
0139: super (dbintrf);
0140: }
0141:
0142: /**
0143: * Standard constructor for a known resource.
0144: *
0145: * @param dbintrf the data store to register
0146: * @param nId the id of this resource
0147: */
0148: public Asset(AbstractDataStoreInterface dbintrf, int nId) {
0149: super (dbintrf, nId);
0150: }
0151:
0152: /**
0153: * Sets the content file associated with this <code>Asset</code>.
0154: *
0155: * @param assetFile the content file
0156: * @throws PopulateException if an error occurs setting the specified
0157: * file to be the content file for this <code>Asset</code>
0158: */
0159: public void setContentFile(File assetFile) throws PopulateException {
0160: String sContentType = m_sContentType;
0161:
0162: if (m_sContentType == null) {
0163: String sExt = assetFile.getName().substring(
0164: assetFile.getName().indexOf(".") + 1);
0165: sContentType = MimeTypeMapping
0166: .getMimeTypeFromExtension(sExt);
0167: setContentType(sContentType);
0168: }
0169:
0170: if (isAssetSavedAsText(sContentType) == true) {
0171: try {
0172: FileReader freader = new FileReader(assetFile);
0173:
0174: StringBuffer sbuf = new StringBuffer();
0175:
0176: int numRead = 0;
0177: int numToRead = 4096;
0178:
0179: char[] buf = new char[numToRead];
0180:
0181: while ((numRead = freader.read(buf, 0, numToRead)) != -1) {
0182: sbuf.append(buf, 0, numRead);
0183: }
0184:
0185: this .setURI(sbuf.toString());
0186:
0187: freader.close();
0188: } catch (IOException e) {
0189: throw new PopulateException(
0190: "Error occured while reading from the file", e);
0191: }
0192: } else {
0193: setURI(assetFile.getAbsolutePath());
0194: }
0195:
0196: setIsChanged(true);
0197: }
0198:
0199: /**
0200: * Returns the mime type of this <code>Asset</code>.
0201: *
0202: * @return the mime type of this <code>Asset</code>
0203: * @throws DataAccessException if an error occurs populating this
0204: * object
0205: */
0206: public String getContentType() throws DataAccessException {
0207: if (isPopulated() == false && m_sContentType == null) {
0208: try {
0209: populateFromDatabase();
0210: } catch (PopulateException e) {
0211: throw new DataAccessException(
0212: "Error occured populating object", e);
0213: }
0214: }
0215:
0216: return m_sContentType;
0217: }
0218:
0219: /**
0220: * Sets the mime type of this <code>Asset</code>.
0221: *
0222: * @param sContentType the mime type
0223: *
0224: * @throws PopulateException if an error occurs setting this mime type value
0225: */
0226: public void setContentType(String sContentType)
0227: throws PopulateException {
0228: if (isPopulated() == true) {
0229: if (m_sContentType.equals(sContentType) == false) {
0230: setIsChanged(true);
0231: }
0232: }
0233:
0234: m_sContentType = sContentType;
0235: }
0236:
0237: /**
0238: * Sets the URI for this <code>Asset</code>.
0239: *
0240: * @param sContent the URI
0241: */
0242: public void setURI(String sContent) {
0243: try {
0244: //make a relative path from absolute path
0245: sContent = getRelativePath(sContent);
0246: } catch (DataAccessException e) {
0247: m_logger.log(Level.WARNING, e.getMessage(), e);
0248: }
0249:
0250: if (isPopulated() == true) {
0251: if (m_sURI.equals(sContent) == false) {
0252: setIsChanged(true);
0253: }
0254: }
0255:
0256: if (sContent.equals(m_sURI) == false) {
0257: setIsContentChanged(true);
0258: }
0259:
0260: m_sURI = sContent;
0261:
0262: }
0263:
0264: /**
0265: * Returns the <code>File</code> associated with this <code>Asset</code>.
0266: *
0267: * @return the <code>File</code> associated with this <code>Asset</code>
0268: * @throws DataAccessException if an error occurs accessing the content
0269: * file of this <code>Asset</code>
0270: */
0271: public File getContentFile() throws DataAccessException {
0272: File file = null;
0273: String sContentType = getContentType();
0274:
0275: if (isAssetSavedAsText(sContentType) == false) {
0276: String sFilename = this .getURI();
0277:
0278: if (sFilename != null) {
0279: file = new File(sFilename);
0280: }
0281: }
0282:
0283: return file;
0284: }
0285:
0286: /**
0287: * Returns the URI associated with this <code>Asset</code>.
0288: *
0289: * @return the URI associated with this <code>Asset</code>
0290: * @throws DataAccessException if an error occurs populating this
0291: * object from the database
0292: */
0293: public String getURI() throws DataAccessException {
0294: if (isPopulated() == false) {
0295: try {
0296: populateFromDatabase();
0297: } catch (PopulateException e) {
0298: throw new DataAccessException(
0299: "Error occured populating data", e);
0300: }
0301: }
0302:
0303: String sURI = null;
0304:
0305: //build full path from relative path
0306: if (m_sURI != null) {
0307:
0308: if (isRelativePath(m_sURI) == true) {
0309: StringBuffer sbuf = new StringBuffer();
0310: String sAssetRoot = getAssetRoot();
0311: sbuf.append(sAssetRoot);
0312:
0313: if (sAssetRoot.endsWith(File.separator) == false
0314: && m_sURI.startsWith(File.separator) == false) {
0315: sbuf.append(File.separatorChar);
0316: }
0317:
0318: sbuf.append(m_sURI);
0319: sURI = sbuf.toString();
0320: } else {
0321: sURI = m_sURI;
0322: }
0323: }
0324:
0325: return sURI;
0326: }
0327:
0328: /**
0329: * Returns <code>true</code> if the specified path is a relative path,
0330: * i.e. does not start with a root
0331: *
0332: * @return
0333: */
0334: private boolean isRelativePath(String sPath) {
0335: boolean bIsRelative = true;
0336:
0337: try {
0338: //if the asset is saved as text then it's not a path to
0339: //a local file and therefore not relative
0340: bIsRelative = (isAssetSavedAsText(getContentType()) == false);
0341: } catch (DataAccessException e) {
0342: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0343: }
0344:
0345: if (bIsRelative == true) {
0346: File[] roots = File.listRoots();
0347:
0348: for (int i = 0; i < roots.length; i++) {
0349: if (sPath.startsWith(roots[i].getAbsolutePath()) == true) {
0350: bIsRelative = false;
0351: break;
0352: }
0353: }
0354: }
0355:
0356: return bIsRelative;
0357: }
0358:
0359: /**
0360: * Copies an existing file to the specified file location.
0361: *
0362: * @param from the current file
0363: * @param to the copy file
0364: * @return <code>true</code> if the operation was successful, otherwise <code>false</code>
0365: */
0366: static public boolean copyFile(File from, File to) {
0367: boolean bMoved = true;
0368:
0369: BufferedInputStream buffIS = null;
0370: BufferedOutputStream buffOS = null;
0371:
0372: try {
0373: buffIS = new BufferedInputStream(new FileInputStream(from));
0374: buffOS = new BufferedOutputStream(new FileOutputStream(to));
0375:
0376: int nByte = buffIS.read();
0377:
0378: while (nByte != -1) {
0379: buffOS.write(nByte);
0380: nByte = buffIS.read();
0381: }
0382: } catch (Exception e) {
0383: bMoved = false;
0384: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0385: } finally {
0386: try {
0387: buffOS.close();
0388: buffIS.close();
0389: } catch (Exception e) {
0390: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0391: }
0392: }
0393:
0394: return bMoved;
0395: }
0396:
0397: /**
0398: * Moves a file from one location to another.
0399: *
0400: * @param from the current file
0401: * @param to the destination file
0402: *
0403: * @return <code>true</code> if this operation was successful, otherwise <code>false</code>
0404: */
0405: static public boolean moveFile(File from, File to) {
0406: boolean bMoved = true;
0407:
0408: BufferedInputStream buffIS = null;
0409: BufferedOutputStream buffOS = null;
0410:
0411: if (from.exists() == true) {
0412:
0413: try {
0414: buffIS = new BufferedInputStream(new FileInputStream(
0415: from));
0416: buffOS = new BufferedOutputStream(new FileOutputStream(
0417: to));
0418:
0419: int nByte = buffIS.read();
0420:
0421: while (nByte != -1) {
0422: buffOS.write(nByte);
0423: nByte = buffIS.read();
0424: }
0425: } catch (Exception e) {
0426: bMoved = false;
0427: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0428: } finally {
0429: try {
0430: buffOS.close();
0431: buffIS.close();
0432: } catch (Exception e) {
0433: m_logger.log(Level.WARNING,
0434: e.getLocalizedMessage(), e);
0435: }
0436: }
0437:
0438: try {
0439: from.delete();
0440: } catch (Exception e) {
0441: bMoved = false;
0442: m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
0443: }
0444: } else {
0445: m_logger.log(Level.WARNING,
0446: "Tried to move non-existing file:"
0447: + from.getAbsolutePath());
0448: bMoved = false;
0449: }
0450:
0451: return bMoved;
0452: }
0453:
0454: /* (non-Javadoc)
0455: * @see org.openharmonise.rm.publishing.Publishable#publish(org.w3c.dom.Element, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
0456: */
0457: public Element publish(Element topEl, HarmoniseOutput output,
0458: State state) throws PublishException {
0459: Element docEl = null;
0460: String sTagName = topEl.getTagName();
0461:
0462: if (sTagName.equals(TAG_URI)) {
0463: docEl = output.createElement(sTagName);
0464:
0465: String sContents = "";
0466:
0467: try {
0468: if (m_nId != NOTDBSAVED_ID) {
0469: sContents = getURI();
0470: }
0471:
0472: if (sContents != null) {
0473: Text txtAssetURL = output
0474: .createTextNode(getFullURL());
0475: docEl.appendChild(txtAssetURL);
0476: }
0477: } catch (DataAccessException e) {
0478: throw new PublishException(
0479: "Error occured publishing asset url", e);
0480: }
0481: } else if (sTagName.equals(TAG_CONTENT_TYPE) == true) {
0482: docEl = output.createElement(sTagName);
0483: try {
0484: Text txt = output.createTextNode(getContentType());
0485: docEl.appendChild(txt);
0486: } catch (DataAccessException e) {
0487: throw new PublishException(
0488: "Error occured getting content type", e);
0489: }
0490: output.copyChildren(docEl, topEl, new Vector());
0491: } else {
0492: docEl = super .publish(topEl, output, state);
0493: }
0494:
0495: return docEl;
0496: }
0497:
0498: /**
0499: * Returns the full URI for this <code>Asset</code>, specifically
0500: * including the installation site URI.
0501: *
0502: * @return the full URI for this <code>Asset</code>
0503: * @throws DataAccessException if an error occurs populating the URI or
0504: * obtaining the site URI
0505: */
0506: public String getFullURL() throws DataAccessException {
0507: String path = "";
0508: String sURI = this .getURI();
0509: String sContentType = getContentType();
0510:
0511: if ((sContentType != null)
0512: && (sContentType.startsWith(TXT_LINK) == false)) {
0513: try {
0514: String sAssetRootFilePath = getAssetRoot();
0515: String sSiteURL = ConfigSettings
0516: .getProperty(PNAME_SITE_URL);
0517: String sAssetWebappURI = ConfigSettings
0518: .getProperty(PNAME_ASSET_WEBAPP_URI);
0519:
0520: if (sURI.startsWith(sAssetRootFilePath) == false) {
0521: throw new DataAccessException(
0522: "Asset path does not start with expected path");
0523: }
0524:
0525: StringBuffer sURL = new StringBuffer();
0526: sURL.append(sSiteURL);
0527:
0528: if (sSiteURL.endsWith("/") == false
0529: && sAssetWebappURI.startsWith("/") == false) {
0530: sURL.append("/");
0531: }
0532:
0533: sURL.append(sAssetWebappURI);
0534: if (sAssetWebappURI.endsWith("/") == false) {
0535: sURL.append("/");
0536: }
0537: sURL.append(sURI.substring(sAssetRootFilePath.length())
0538: .replace(File.separatorChar, '/'));
0539:
0540: path = sURL.toString();
0541:
0542: } catch (ConfigException e) {
0543: throw new DataAccessException(
0544: "Error occured accessing config property", e);
0545: }
0546:
0547: } else {
0548: path = sURI;
0549: }
0550:
0551: return path;
0552: }
0553:
0554: /* (non-Javadoc)
0555: * @see org.openharmonise.rm.resources.AbstractEditableObject#delete(boolean)
0556: */
0557: public void delete(boolean bDeleteHistory)
0558: throws DataStoreException, DataAccessException,
0559: EditException, PopulateException {
0560: File file = null;
0561:
0562: if (bDeleteHistory == true) {
0563: file = getContentFile();
0564: }
0565:
0566: super .delete(bDeleteHistory);
0567:
0568: if (file != null) {
0569: file.delete();
0570: }
0571: }
0572:
0573: /* (non-Javadoc)
0574: * @see org.openharmonise.rm.dsi.DataStoreObject#getDBTableName()
0575: */
0576: public String getDBTableName() {
0577: return TBL_ASSET;
0578: }
0579:
0580: /* (non-Javadoc)
0581: * @see org.openharmonise.rm.publishing.Publishable#getTagName()
0582: */
0583: public String getTagName() {
0584: return TAG_ASSET;
0585: }
0586:
0587: /**
0588: * Returns the root file path for assets
0589: *
0590: * @return
0591: * @throws DataAccessException
0592: */
0593: public String getAssetRoot() throws DataAccessException {
0594: String sRoot = null;
0595:
0596: try {
0597: sRoot = ConfigSettings
0598: .getProperty(PNAME_ASSET_ROOT_FILEPATH);
0599: } catch (ConfigException e) {
0600: throw new DataAccessException(e);
0601: }
0602:
0603: return sRoot;
0604: }
0605:
0606: /* (non-Javadoc)
0607: * @see org.openharmonise.rm.dsi.DataStoreObject#getInstanceJoinConditions(java.lang.String, boolean)
0608: */
0609: public JoinConditions getInstanceJoinConditions(String sObjectTag,
0610: boolean bIsOuter) throws DataStoreException {
0611:
0612: return null;
0613: }
0614:
0615: /* (non-Javadoc)
0616: * @see org.openharmonise.rm.resources.AbstractChildObject#getParentObjectClassName()
0617: */
0618: public String getParentObjectClassName() {
0619:
0620: return Section.class.getName();
0621: }
0622:
0623: /* (non-Javadoc)
0624: * @see org.openharmonise.rm.dsi.DataStoreObject#getInstanceColumnRef(java.lang.String, boolean)
0625: */
0626: public ColumnRef getInstanceColumnRef(String sColumn,
0627: boolean bIsHist) throws DataStoreException {
0628: ColumnRef colref = null;
0629:
0630: String sTable = getTableName(bIsHist);
0631:
0632: if (sColumn.equals(CLMN_URI) == true) {
0633: colref = new ColumnRef(sTable, CLMN_URI, ColumnRef.TEXT);
0634: } else if (sColumn.equals(CLMN_MIME_TYPE) == true) {
0635: colref = new ColumnRef(sTable, CLMN_MIME_TYPE,
0636: ColumnRef.TEXT);
0637: } else {
0638: colref = super .getInstanceColumnRef(sColumn, bIsHist);
0639: }
0640:
0641: return colref;
0642: }
0643:
0644: /*--------------------------------------------------------------------------
0645: Protected Methods
0646: ---------------------------------------------------------------------------*/
0647:
0648: /**
0649: * Returns a <code>File</code> representing a new directory in the
0650: * file system. Any parent directories which do not already exist will
0651: * be created.
0652: *
0653: * @param sDir The full path of the directory to create
0654: * @return a <code>File</code> representing a new directory in the
0655: * file system
0656: */
0657: static protected File createDir(String sDir) {
0658: StringTokenizer tokens = new StringTokenizer(sDir,
0659: File.separator);
0660: File dirNext = null;
0661: String sNext = null;
0662: StringBuffer sSoFar = new StringBuffer();
0663:
0664: if (sDir.startsWith(File.separator)) {
0665: sSoFar.append(File.separator);
0666: } else {
0667: sNext = tokens.nextToken();
0668: sSoFar.append(sNext);
0669: sSoFar.append(File.separator);
0670: }
0671:
0672: while (tokens.hasMoreTokens()) {
0673: sNext = tokens.nextToken();
0674: sSoFar.append(sNext);
0675: dirNext = new File(sSoFar.toString());
0676:
0677: if (dirNext.exists() == false) {
0678: dirNext.mkdir();
0679: }
0680: }
0681:
0682: return dirNext;
0683: }
0684:
0685: /* (non-Javadoc)
0686: * @see org.openharmonise.rm.resources.AbstractEditableObject#addDataToSave(org.openharmonise.commons.dsi.dml.InsertStatement)
0687: */
0688: protected void addDataToSave(InsertStatement insert)
0689: throws DataStoreException {
0690:
0691: try {
0692: if (getContentType().startsWith(TXT_LINK) == false
0693: && isContentChanged() == true) {
0694: String sFileName = getURI();
0695:
0696: // need to discover if the changes in the asset mean the file should be moved
0697: File newFile = createFile();
0698:
0699: if (sFileName.equals(newFile.getAbsolutePath()) == false) {
0700: boolean bSuccess = true;
0701:
0702: //if content has changed move the file
0703: //otherwise, we're just creating a new version and we need to
0704: //keep the old one
0705: if (m_bIsContentChanged == true) {
0706: bSuccess = moveFile(new File(sFileName),
0707: newFile);
0708: } else {
0709: bSuccess = copyFile(new File(sFileName),
0710: newFile);
0711: }
0712:
0713: if (bSuccess == false) {
0714: throw new DataStoreException(
0715: "File manipulation failed");
0716: }
0717:
0718: }
0719:
0720: m_sURI = newFile.getAbsolutePath();
0721: }
0722: } catch (DataAccessException e) {
0723: throw new DataStoreException(
0724: "Error occured accessing object data", e);
0725: } catch (AssetException e) {
0726: throw new DataStoreException("Error handling asset", e);
0727: } catch (ConfigException e) {
0728: throw new DataStoreException(
0729: "Error accessing config setting", e);
0730: }
0731:
0732: insert.addColumnValue(getInstanceColumnRef(CLMN_MIME_TYPE,
0733: isHistorical()), m_sContentType);
0734:
0735: try {
0736:
0737: //ensure the saved path is a relative path
0738: m_sURI = getRelativePath(m_sURI);
0739:
0740: insert.addColumnValue(getInstanceColumnRef(CLMN_URI,
0741: isHistorical()), m_sURI);
0742: } catch (DataAccessException e) {
0743: throw new DataStoreException(e);
0744: }
0745:
0746: super .addDataToSave(insert);
0747:
0748: //reset content changed flag
0749: m_bIsContentChanged = false;
0750: }
0751:
0752: /* (non-Javadoc)
0753: * @see org.openharmonise.rm.resources.AbstractEditableObject#saveCoreData()
0754: */
0755: protected void saveCoreData() throws EditException {
0756: super .saveCoreData();
0757: }
0758:
0759: /* (non-Javadoc)
0760: * @see org.openharmonise.rm.resources.AbstractObject#populateFromResultSetRow(java.sql.ResultSet, org.openharmonise.commons.dsi.dml.SelectStatement)
0761: */
0762: protected void populateFromResultSetRow(ResultSet rs,
0763: SelectStatement select) throws PopulateException {
0764: if (isPopulated() == false) {
0765:
0766: String sTemp = null;
0767:
0768: try {
0769:
0770: ColumnRefCache cache = ColumnRefCache.getInstance();
0771: boolean bIsHist = isHistorical();
0772:
0773: ColumnRef colref = cache.getColumnRef(this , CLMN_URI,
0774: bIsHist);
0775: if (select.containsSelectColumn(colref) == true) {
0776: sTemp = rs.getString(select
0777: .getResultSetIndex(colref));
0778:
0779: if ((sTemp != null) && (sTemp.length() > 0)) {
0780: if ((m_sURI == null) || (m_sURI.length() == 0)) {
0781: m_sURI = sTemp;
0782: } else if (m_sURI.equals(sTemp) == false) {
0783: setIsChanged(true);
0784: }
0785: }
0786: }
0787:
0788: colref = cache.getColumnRef(this , CLMN_MIME_TYPE,
0789: bIsHist);
0790: if (select.containsSelectColumn(colref) == true) {
0791: sTemp = rs.getString(select
0792: .getResultSetIndex(colref));
0793:
0794: if ((sTemp != null) && (sTemp.length() > 0)) {
0795: if ((m_sContentType == null)
0796: || (m_sContentType.length() == 0)) {
0797: m_sContentType = sTemp;
0798: } else if (m_sContentType.equals(sTemp) == false) {
0799: setIsChanged(true);
0800: }
0801: }
0802: }
0803: } catch (SQLException e) {
0804: throw new PopulateException("Error occured populating",
0805: e);
0806: } catch (CacheException e) {
0807: throw new PopulateException("Error occured populating",
0808: e);
0809: }
0810:
0811: super .populateFromResultSetRow(rs, select);
0812: }
0813:
0814: }
0815:
0816: /* (non-Javadoc)
0817: * @see org.openharmonise.rm.resources.AbstractObject#addColumnsToPopulateQuery(org.openharmonise.commons.dsi.dml.SelectStatement, boolean)
0818: */
0819: protected void addColumnsToPopulateQuery(SelectStatement select,
0820: boolean bIsHist) throws DataStoreException {
0821:
0822: try {
0823: ColumnRefCache cache = ColumnRefCache.getInstance();
0824:
0825: select.addSelectColumn(cache.getColumnRef(this , CLMN_URI,
0826: bIsHist));
0827:
0828: select.addSelectColumn(cache.getColumnRef(this ,
0829: CLMN_MIME_TYPE, bIsHist));
0830: } catch (CacheException e) {
0831: throw new DataStoreException(e.getLocalizedMessage(), e);
0832: }
0833:
0834: super .addColumnsToPopulateQuery(select, bIsHist);
0835:
0836: }
0837:
0838: /*--------------------------------------------------------------------------
0839: Private Methods
0840: ---------------------------------------------------------------------------*/
0841:
0842: /**
0843: * Returns a <code>File</code> which has a path correct for the current
0844: * <code>Asset</code>.
0845: *
0846: * Note: the file path will follow the pattern
0847: * <asset root>/<first letter of asset name>/<asset name>
0848: * for example 'C:\assets\F\foo.gif'
0849: *
0850: *
0851: * @return a <code>File</code> which has a path correct for the current
0852: * <code>Asset</code>.
0853: * @throws AssetException if the parent directory of the new content
0854: * file does not exist
0855: * @throws ConfigException if an error occurs obtaining the asset root
0856: * configuration property
0857: * @throws DataAccessException if an error occurs getting this object's
0858: * name, used for the file name
0859: */
0860: protected File createFile() throws AssetException, ConfigException,
0861: DataAccessException {
0862: String sFilePath = null;
0863:
0864: sFilePath = ConfigSettings.getProperty(
0865: PNAME_ASSET_ROOT_FILEPATH).replace('/',
0866: File.separatorChar);
0867:
0868: String sName = getName();
0869: String sSuffix = MimeTypeMapping
0870: .getExtensionFromMimeType(getContentType());
0871:
0872: StringBuffer sFullPath = new StringBuffer();
0873: sFullPath.append(sFilePath);
0874:
0875: //esure there's a separator at the end of the path
0876: if (sFilePath.charAt(sFilePath.length() - 1) != File.separatorChar) {
0877: sFullPath.append(File.separatorChar);
0878: }
0879:
0880: //ensure file is in a directory under the root which matches the first
0881: //letter of this Asset's name
0882: sFullPath.append(Character.toUpperCase(sName.charAt(0)));
0883:
0884: sFullPath.append(File.separatorChar);
0885:
0886: sFullPath.append(sName).append("_").append(getKey());
0887: sFullPath.append(".").append(sSuffix);
0888:
0889: //check path is valid, i.e. that parent exists
0890: File test = new File(sFullPath.toString());
0891:
0892: if (ensureParentExists(test) == false) {
0893: throw new AssetException(
0894: "Trouble creating asset file - parent does not exist");
0895: }
0896:
0897: int nCount = 1;
0898:
0899: //in the unlikely event that there already exists a file with the same name
0900: //rename it with a count added
0901: while (test.exists()) {
0902: sFullPath = new StringBuffer();
0903: sFullPath.append(sFilePath);
0904: if (sFilePath.endsWith(File.separator) == false) {
0905: sFullPath.append(File.separatorChar);
0906: }
0907: sFullPath.append(sName);
0908: sFullPath.append("_[");
0909: sFullPath.append(nCount);
0910: sFullPath.append("]");
0911: sFullPath.append(".");
0912: sFullPath.append(sSuffix);
0913: test = new File(sFullPath.toString());
0914: nCount++;
0915: }
0916:
0917: return test;
0918: }
0919:
0920: /**
0921: * Returns <code>true</code> if the parent of the given <code>File</code> exists.
0922: * If the parent does not exist an attempt will be made to create it, if this
0923: * fails the method will return <code>false</code>.
0924: *
0925: * @param file the file whose parent's existance is to be tested
0926: * @return <code>true</code> if the parent of the given <code>File</code> exists
0927: */
0928: protected boolean ensureParentExists(File file) {
0929: File parent = file.getParentFile();
0930:
0931: boolean breturn = parent.exists();
0932:
0933: if (breturn == false) {
0934: if (ensureParentExists(parent) == true) {
0935:
0936: breturn = parent.mkdir();
0937: }
0938: }
0939:
0940: return breturn;
0941: }
0942:
0943: /* (non-Javadoc)
0944: * @see org.openharmonise.rm.resources.AbstractEditableObject#saveNonCoreData()
0945: */
0946: protected void saveNonCoreData() throws EditException {
0947:
0948: }
0949:
0950: /**
0951: * Returns <code>true</code> if the URI value for this <code>Asset</code>
0952: * has changed.
0953: *
0954: * @return <code>true</code> if the URI value for this <code>Asset</code>
0955: * has changed
0956: */
0957: public boolean isContentChanged() {
0958: return m_bIsContentChanged;
0959: }
0960:
0961: /**
0962: * Sets the value of the content changed flag.
0963: *
0964: * @param bContentChanged <code>true</code> to indicate a change in the content, otherwise <code>false</code>
0965: */
0966: public void setIsContentChanged(boolean bContentChanged) {
0967: m_bIsContentChanged = bContentChanged;
0968: }
0969:
0970: /* (non-Javadoc)
0971: * @see org.openharmonise.rm.resources.AbstractObject#clear()
0972: */
0973: public void clear() {
0974: m_sContentType = null;
0975: m_sURI = null;
0976: m_bIsContentChanged = false;
0977: super .clear();
0978: }
0979:
0980: /**
0981: * Returns <code>true</code> if an asset of the specified mime type
0982: * should be saved in DB as text rather than as a file.
0983: *
0984: * @param sContentType the mime type
0985: * @return <code>true</code> if asset should be saved in DB as
0986: * text rather than as a file
0987: */
0988: protected boolean isAssetSavedAsText(String sContentType) {
0989: return sContentType.startsWith(TXT_LINK)
0990: || sContentType.startsWith(TXT_TEXT);
0991: }
0992:
0993: /**
0994: * Returns the relative path for the given absolute path.
0995: *
0996: * Note: this assumes that the absolute path starts with the
0997: * current asset root path
0998: *
0999: * @param sAbsolutePath
1000: * @return
1001: * @throws DataAccessException
1002: */
1003: protected String getRelativePath(String sAbsolutePath)
1004: throws DataAccessException {
1005: String sRelPath = sAbsolutePath;
1006:
1007: String sAssetRoot = getAssetRoot();
1008:
1009: if (sAbsolutePath != null
1010: && sAbsolutePath.startsWith(sAssetRoot) == true) {
1011: sRelPath = sAbsolutePath.substring(sAssetRoot.length());
1012: }
1013:
1014: return sRelPath;
1015: }
1016:
1017: }
|