private ExternalLocation addExtLocation(Namespace extNamespace, String extLabel,
			Address extAddr, boolean isFunction, SourceType sourceType, boolean reuseExisting)
			throws InvalidInputException {
		if (extNamespace == null) {
			extNamespace = getLibraryScope(Library.UNKNOWN);
			if (extNamespace == null) {
				try {
					extNamespace = addExternalLibraryName(Library.UNKNOWN, SourceType.ANALYSIS);
				}
				catch (DuplicateNameException e) {
					// TODO: really need to reserve the unknown namespace name
					throw new InvalidInputException(
						"Failed to establish " + Library.UNKNOWN + " library");
				}
			}
		}
		else if (!extNamespace.isExternal()) {
			throw new InvalidInputException("The namespace must be an external namespace.");
		}
		sourceType = checkExternalLabel(extLabel, extAddr, sourceType);
		if (extAddr != null) {
			if (!extAddr.isLoadedMemoryAddress()) {
				throw new InvalidInputException("Invalid memory address: " + extAddr);
			}
			AddressSpace space = extAddr.getAddressSpace();
			if (!space.equals(program.getAddressFactory().getAddressSpace(space.getName()))) {
				throw new InvalidInputException(
					"Memory address not defined for program: " + extAddr);
			}
		}
		lock.acquire();
		try {
			if (sourceType == SourceType.DEFAULT) {
				extLabel = null;
			}
			else if (StringUtils.isBlank(extLabel) || SymbolUtilities
					.isReservedExternalDefaultName(extLabel, addrMap.getAddressFactory())) {
				extLabel = null; // force use of address
			}
			if (extAddr != null || reuseExisting) {

				ExternalLocationDB extLoc = (ExternalLocationDB) getExtLocation(extNamespace,
					extLabel, extAddr, reuseExisting);

				if (extLoc != null) {

					// if there is already a location with the address, then we must use it
					if (extLabel != null && !extLabel.equals(extLoc.getLabel())) {
						extLoc.setLabel(extLabel, sourceType);
					}
					if (isFunction) {
						// transform to a function if needed
						extLoc = (ExternalLocationDB) createFunction(extLoc).getExternalLocation();
					}
					return extLoc;
				}
			}

			// ok can't or don't want to reuse an existing one, so make a new one.
			MemorySymbol s;
			Address externalSpaceAddress = symbolMgr.getNextExternalSymbolAddress();
			if (isFunction) {
				FunctionDB function = functionMgr.createExternalFunction(externalSpaceAddress,
					extLabel, extNamespace, null, extAddr, sourceType);
				s = (FunctionSymbol) function.getSymbol();
			}
			else {
				s = symbolMgr.createExternalCodeSymbol(externalSpaceAddress, extLabel, extNamespace,
					sourceType, null, extAddr);
			}
			return new ExternalLocationDB(this, s);
		}
		catch (IOException e) {
			program.dbError(e); // will not return
			return null;
		}
		finally {
			lock.release();
		}
	}
Constructs a new ExternalManagerDB
@param handle the open database handle
@param addrMap the address map
@param openMode the program open mode.
@param lock the program synchronization lock
@param monitor the progress monitor used when upgrading
@throws CancelledException if the user cancelled while an upgrade was occurring
@throws IOException if a database io error occurs.
@throws VersionException if the database version does not match the expected version
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/external/ExternalManagerDB.java