001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others.
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 * Contributors:
017 *     Stephane Lacoin
018 */
019package org.nuxeo.ecm.core.api;
020
021import java.io.InvalidObjectException;
022import java.io.ObjectStreamException;
023import java.security.Principal;
024
025import org.nuxeo.runtime.transaction.TransactionHelper;
026
027/**
028 * Document repository reference including the principal owner of the session.
029 *
030 * @since 7.10
031 * @author Stephane Lacoin at Nuxeo (aka matic)
032 */
033public class InstanceRef implements DocumentRef {
034
035    private static final long serialVersionUID = 1L;
036
037    final String repositoryName;
038
039    final Principal principal;
040
041    final DocumentRef ref;
042
043    transient DocumentModel referent;
044
045    public InstanceRef(DocumentModel doc, Principal principal) {
046        if (doc.getRef() == null) {
047            throw new NullPointerException("document as no reference yet");
048        }
049        referent = doc;
050        repositoryName = doc.getRepositoryName();
051        this.principal = principal;
052        ref = doc.getRef();
053    }
054
055    @Override
056    public int type() {
057        return -1;
058    }
059
060    @Override
061    public Object reference() {
062        return referent;
063    }
064
065    private Object readResolve() throws ObjectStreamException {
066        // we need a transaction for this
067        boolean started = false;
068        if (!TransactionHelper.isTransactionActiveOrMarkedRollback()) {
069            started = TransactionHelper.startTransaction();
070        }
071        try {
072            try (CoreSession session = CoreInstance.openCoreSession(repositoryName, principal)) {
073                referent = session.getDocument(ref);
074                referent.detach(true);
075                return referent;
076            }
077        } catch (RuntimeException cause) {
078            InvalidObjectException error = new InvalidObjectException(
079                    "Cannot refetch " + ref + " from " + repositoryName);
080            error.initCause(cause);
081            throw error;
082        } finally {
083            if (started) {
084                TransactionHelper.commitOrRollbackTransaction();
085            }
086        }
087    }
088
089    @Override
090    public int hashCode() {
091        final int prime = 31;
092        int result = 1;
093        result = prime * result + ((repositoryName == null) ? 0 : repositoryName.hashCode());
094        result = prime * result + ((ref == null) ? 0 : ref.hashCode());
095        result = prime * result + ((principal == null) ? 0 : principal.hashCode());
096        return result;
097    }
098
099    @Override
100    public boolean equals(Object obj) {
101        if (this == obj) {
102            return true;
103        }
104        if (obj == null) {
105            return false;
106        }
107        if (getClass() != obj.getClass()) {
108            return false;
109        }
110        InstanceRef other = (InstanceRef) obj;
111        if (repositoryName == null) {
112            if (other.repositoryName != null) {
113                return false;
114            }
115        } else if (!repositoryName.equals(other.repositoryName)) {
116            return false;
117        }
118        if (ref == null) {
119            if (other.ref != null) {
120                return false;
121            }
122        } else if (!ref.equals(other.ref)) {
123            return false;
124        }
125        if (principal == null) {
126            if (other.principal != null) {
127                return false;
128            }
129        } else if (!principal.equals(other.principal)) {
130            return false;
131        }
132        return true;
133    }
134}