001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.outerj.daisy.books.store.impl;
017:
018: import org.outerj.daisy.books.store.*;
019: import org.outerj.daisy.repository.Repository;
020: import org.apache.cocoon.util.WildcardMatcherHelper;
021: import org.outerx.daisy.x10Bookstoremeta.ResourcePropertiesDocument;
022:
023: import java.io.File;
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.io.OutputStream;
027: import java.net.URI;
028:
029: public class UserBookInstance implements BookInstance {
030: private CommonBookInstance delegate;
031: private Repository repository;
032: private boolean locked = false;
033:
034: /**
035: * @param locked normally always false, except when a new (and locked) book instance was created
036: */
037: UserBookInstance(CommonBookInstance delegate,
038: Repository repository, boolean locked) {
039: this .delegate = delegate;
040: this .repository = repository;
041: this .locked = locked;
042: }
043:
044: File getDirectory() {
045: return delegate.getDirectory();
046: }
047:
048: private boolean isLockedBySomeoneElse() {
049: if (!locked) {
050: return delegate.isLocked();
051: } else {
052: return false;
053: }
054: }
055:
056: private boolean isLockedByMe() {
057: return locked;
058: }
059:
060: private AclResult checkCanRead() {
061: if (isLockedByMe())
062: return new AclResult(true, true);
063: if (isLockedBySomeoneElse())
064: throw new BookStoreException(
065: "This book instance is current locked for updating. Try again later.");
066: AclResult aclResult = BookAclEvaluator.evaluate(delegate
067: .getAcl(), repository.getUserId(), repository
068: .getActiveRoleIds());
069: if (!aclResult.canRead())
070: throw new BookStoreAccessDeniedException();
071: return aclResult;
072: }
073:
074: private void checkCanRead(String path) {
075: AclResult result = checkCanRead();
076: if (!result.canManage()) {
077: // If someone only has read access but not write access, we do not allow access
078: // to all resources in the book instance.
079: if (path.charAt(0) != '/')
080: path = "/" + path;
081: boolean ok = false;
082: for (int i = 0; i < PUBLIC_RESOURCES_PATTERNS.length; i++) {
083: if (WildcardMatcherHelper.match(
084: PUBLIC_RESOURCES_PATTERNS[i], path) != null) {
085: ok = true;
086: break;
087: }
088: }
089: if (!ok)
090: throw new BookStoreAccessDeniedException(
091: "Access denied to " + path);
092: }
093: }
094:
095: private void checkCanWrite() {
096: if (!isLockedByMe())
097: throw new BookStoreException(
098: "A lock is required to update a book instance.");
099: AclResult aclResult = BookAclEvaluator.evaluate(delegate
100: .getAcl(), repository.getUserId(), repository
101: .getActiveRoleIds());
102: if (!aclResult.canRead())
103: throw new BookStoreAccessDeniedException();
104: }
105:
106: public void lock() {
107: if (isLockedByMe() || isLockedBySomeoneElse()) {
108: throw new BookStoreException(
109: "This book instance is alredy locked.");
110: }
111:
112: AclResult aclResult = BookAclEvaluator.evaluate(delegate
113: .getAcl(), repository.getUserId(), repository
114: .getActiveRoleIds());
115: if (!aclResult.canManage())
116: throw new BookStoreAccessDeniedException(
117: "You are not allowed to take a lock on the book instance \""
118: + getName() + "\".");
119:
120: File lockFile = new File(delegate.getDirectory(),
121: CommonBookInstance.LOCK_FILE_NAME);
122: try {
123: if (lockFile.createNewFile()) {
124: locked = true;
125: } else {
126: throw new BookStoreException(
127: "This book instance is already locked.");
128: }
129: } catch (IOException e) {
130: throw new BookStoreException(
131: "IO Exception while trying to take a lock on a book instance.",
132: e);
133: }
134: }
135:
136: public void unlock() {
137: if (!isLockedByMe()) {
138: throw new BookStoreException(
139: "You do not have a lock on this book instance.");
140: }
141:
142: if (locked) {
143: File lockFile = new File(delegate.getDirectory(),
144: CommonBookInstance.LOCK_FILE_NAME);
145: boolean success = lockFile.delete();
146: if (!success)
147: throw new BookStoreException(
148: "Could not remove lock on book instance.");
149: locked = false;
150: }
151: }
152:
153: public String getName() {
154: return delegate.getName();
155: }
156:
157: private static final String[] PUBLIC_RESOURCES_PATTERNS = new String[] {
158: "/data/resources/**", "/publications/*/output/**" };
159:
160: public InputStream getResource(String path) {
161: if (path == null || path.length() == 0)
162: throw new IllegalArgumentException(
163: "path argument can not be null or empty");
164: checkCanRead(path);
165: return delegate.getResource(path);
166: }
167:
168: public ResourcePropertiesDocument getResourceProperties(String path) {
169: if (path == null || path.length() == 0)
170: throw new IllegalArgumentException(
171: "path argument can not be null or empty");
172: checkCanRead(path);
173: return delegate.getResourceProperties(path);
174: }
175:
176: public void storeResource(String path, InputStream is) {
177: checkCanWrite();
178: delegate.storeResource(path, is);
179: }
180:
181: public void storeResourceProperties(String path,
182: ResourcePropertiesDocument resourcePropertiesDocument) {
183: checkCanWrite();
184: delegate.storeResourceProperties(path,
185: resourcePropertiesDocument);
186: }
187:
188: public OutputStream getResourceOutputStream(String path)
189: throws IOException {
190: checkCanWrite();
191: return delegate.getResourceOutputStream(path);
192: }
193:
194: public boolean rename(String path, String newName) {
195: checkCanWrite();
196: return delegate.rename(path, newName);
197: }
198:
199: public boolean exists(String path) {
200: checkCanRead(path);
201: return delegate.exists(path);
202: }
203:
204: public long getLastModified(String path) {
205: checkCanRead(path);
206: return delegate.getLastModified(path);
207: }
208:
209: public long getContentLength(String path) {
210: checkCanRead(path);
211: return delegate.getContentLength(path);
212: }
213:
214: public BookAcl getAcl() {
215: checkCanRead();
216: return delegate.getAcl();
217: }
218:
219: public void setAcl(BookAcl bookAcl) {
220: checkCanWrite();
221: delegate.setAcl(bookAcl);
222: }
223:
224: public boolean canManage() {
225: AclResult aclResult = BookAclEvaluator.evaluate(delegate
226: .getAcl(), repository.getUserId(), repository
227: .getActiveRoleIds());
228: return aclResult.canManage();
229: }
230:
231: public URI getResourceURI(String path) {
232: checkCanRead(path);
233: return delegate.getResourceURI(path);
234: }
235:
236: public PublicationsInfo getPublicationsInfo() {
237: checkCanRead();
238: return delegate.getPublicationsInfo();
239: }
240:
241: public void addPublication(PublicationInfo publicationInfo) {
242: checkCanWrite();
243: delegate.addPublication(publicationInfo);
244: }
245:
246: public void setPublications(PublicationsInfo publicationsInfo) {
247: checkCanWrite();
248: delegate.setPublications(publicationsInfo);
249: }
250:
251: public BookInstanceMetaData getMetaData() {
252: checkCanRead();
253: return delegate.getMetaData();
254: }
255:
256: public void setMetaData(BookInstanceMetaData metaData) {
257: checkCanWrite();
258: delegate.setMetaData(metaData);
259: }
260:
261: public String[] getDescendantPaths(String path) {
262: checkCanRead();
263: return delegate.getDescendantPaths(path);
264: }
265: }
|